← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Commit message:
lp.code: Apply "pyupgrade --py3-plus"

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/413331
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:pyupgrade-py3-code into launchpad:master.
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 91cb020..4691daf 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -22,3 +22,5 @@ b6725842a2470e3927bb73bf400c4476a06ee3ba
 474f07ab7c3f28d8b6b8e4f1bd4c56832cec3fab
 # apply pyupgrade --py3-plus to lp.code.browser
 47ee1259461aa54ad7ee967e85f6131be2b74125
+# apply pyupgrade --py3-plus to lp.code
+cee9b128d3e49ca814464eeeeec50e6bcabcc4ba
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 47ab095..d82d7fe 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -48,7 +48,7 @@ repos:
             |bugs
             |buildmaster
             |charms
-            |code/browser
+            |code
           )/
 -   repo: https://github.com/PyCQA/isort
     rev: 5.9.2
diff --git a/lib/lp/code/adapters/tests/test_gitrepository.py b/lib/lp/code/adapters/tests/test_gitrepository.py
index 5363a15..9983274 100644
--- a/lib/lp/code/adapters/tests/test_gitrepository.py
+++ b/lib/lp/code/adapters/tests/test_gitrepository.py
@@ -19,7 +19,7 @@ class TestGitRepositoryDelta(TestCaseWithFactory):
 
     def test_no_modification(self):
         # If there are no modifications, no delta is returned.
-        repository = self.factory.makeGitRepository(name=u"foo")
+        repository = self.factory.makeGitRepository(name="foo")
         old_repository = Snapshot(repository, providing=providedBy(repository))
         delta = GitRepositoryDelta.construct(
             old_repository, repository, repository.owner)
@@ -30,18 +30,18 @@ class TestGitRepositoryDelta(TestCaseWithFactory):
         owner = self.factory.makePerson(name="person")
         project = self.factory.makeProduct(name="project")
         repository = self.factory.makeGitRepository(
-            owner=owner, target=project, name=u"foo")
+            owner=owner, target=project, name="foo")
         old_repository = Snapshot(repository, providing=providedBy(repository))
         with person_logged_in(repository.owner):
-            repository.setName(u"bar", repository.owner)
+            repository.setName("bar", repository.owner)
         delta = GitRepositoryDelta.construct(old_repository, repository, owner)
         self.assertIsNotNone(delta)
         self.assertThat(delta, MatchesStructure.byEquality(
             name={
-                "old": u"foo",
-                "new": u"bar",
+                "old": "foo",
+                "new": "bar",
                 },
             git_identity={
-                "old": u"lp:~person/project/+git/foo",
-                "new": u"lp:~person/project/+git/bar",
+                "old": "lp:~person/project/+git/foo",
+                "new": "lp:~person/project/+git/bar",
                 }))
diff --git a/lib/lp/code/errors.py b/lib/lp/code/errors.py
index 885662e..a4dc375 100644
--- a/lib/lp/code/errors.py
+++ b/lib/lp/code/errors.py
@@ -70,7 +70,6 @@ import http.client
 
 from breezy.plugins.builder.recipe import RecipeParseError
 from lazr.restful.declarations import error_status
-import six
 
 from lp.app.errors import (
     NameLookupFailed,
@@ -203,8 +202,7 @@ class CannotUpgradeBranch(Exception):
     """"Made for subclassing."""
 
     def __init__(self, branch):
-        super(CannotUpgradeBranch, self).__init__(
-            self._msg_template % branch.bzr_identity)
+        super().__init__(self._msg_template % branch.bzr_identity)
         self.branch = branch
 
 
@@ -254,7 +252,7 @@ class BranchMergeProposalExists(InvalidBranchMergeProposal):
             display_name = "displayname"
         else:
             display_name = "display_name"
-        super(BranchMergeProposalExists, self).__init__(
+        super().__init__(
                 'There is already a branch merge proposal registered for '
                 'branch %s to land on %s that is still active.' %
                 (getattr(existing_proposal.merge_source, display_name),
@@ -363,7 +361,7 @@ class BranchFileNotFound(BranchHostingFault):
     """Raised when a file does not exist in a branch."""
 
     def __init__(self, branch_id, filename=None, file_id=None, rev=None):
-        super(BranchFileNotFound, self).__init__()
+        super().__init__()
         if (filename is None) == (file_id is None):
             raise AssertionError(
                 "Exactly one of filename and file_id must be given.")
@@ -416,7 +414,6 @@ class GitRepositoryCreationForbidden(GitRepositoryCreationException):
     """
 
 
-@six.python_2_unicode_compatible
 @error_status(http.client.BAD_REQUEST)
 class GitRepositoryCreatorNotMemberOfOwnerTeam(GitRepositoryCreationException):
     """Git repository creator is not a member of the owner team.
@@ -435,7 +432,6 @@ class GitRepositoryCreatorNotMemberOfOwnerTeam(GitRepositoryCreationException):
         return message
 
 
-@six.python_2_unicode_compatible
 @error_status(http.client.BAD_REQUEST)
 class GitRepositoryCreatorNotOwner(GitRepositoryCreationException):
     """A user cannot create a Git repository belonging to another user.
@@ -458,7 +454,7 @@ class GitRepositoryCreationFault(Exception):
     """Raised when there is a hosting fault creating a Git repository."""
 
     def __init__(self, message, path):
-        super(GitRepositoryCreationFault, self).__init__(message)
+        super().__init__(message)
         self.path = path
 
 
@@ -470,7 +466,7 @@ class GitRepositoryBlobNotFound(GitRepositoryScanFault):
     """Raised when a blob does not exist in a repository."""
 
     def __init__(self, path, filename, rev=None):
-        super(GitRepositoryBlobNotFound, self).__init__()
+        super().__init__()
         self.path = path
         self.filename = filename
         self.rev = rev
@@ -486,7 +482,7 @@ class GitRepositoryBlobUnsupportedRemote(Exception):
     """Raised when trying to fetch a blob from an unsupported remote host."""
 
     def __init__(self, repository_url):
-        super(GitRepositoryBlobUnsupportedRemote, self).__init__()
+        super().__init__()
         self.repository_url = repository_url
 
     def __str__(self):
@@ -565,7 +561,7 @@ class CannotModifyNonHostedGitRepository(Exception):
     """Raised when trying to modify a non-hosted Git repository."""
 
     def __init__(self, repository):
-        super(CannotModifyNonHostedGitRepository, self).__init__(
+        super().__init__(
             "Cannot modify non-hosted Git repository %s." %
             repository.display_name)
 
@@ -579,7 +575,7 @@ class CodeImportAlreadyRequested(Exception):
     """Raised when the user requests an import that is already requested."""
 
     def __init__(self, msg, requesting_user):
-        super(CodeImportAlreadyRequested, self).__init__(msg)
+        super().__init__(msg)
         self.requesting_user = requesting_user
 
 
@@ -593,7 +589,7 @@ class CodeImportInvalidTargetType(Exception):
     """Raised for code imports with an invalid target for their type."""
 
     def __init__(self, target, target_rcs_type):
-        super(CodeImportInvalidTargetType, self).__init__(
+        super().__init__(
             "Objects of type %s do not support code imports targeting %s." %
             (target.__class__.__name__, target_rcs_type))
 
@@ -603,7 +599,7 @@ class TooNewRecipeFormat(Exception):
     """The format of the recipe supplied was too new."""
 
     def __init__(self, supplied_format, newest_supported):
-        super(TooNewRecipeFormat, self).__init__()
+        super().__init__()
         self.supplied_format = supplied_format
         self.newest_supported = newest_supported
 
diff --git a/lib/lp/code/event/git.py b/lib/lp/code/event/git.py
index bc89694..317c687 100644
--- a/lib/lp/code/event/git.py
+++ b/lib/lp/code/event/git.py
@@ -18,6 +18,6 @@ class GitRefsUpdatedEvent(ObjectEvent):
     """See `IGitRefsUpdatedEvent`."""
 
     def __init__(self, repository, paths, logger):
-        super(GitRefsUpdatedEvent, self).__init__(repository)
+        super().__init__(repository)
         self.paths = paths
         self.logger = logger
diff --git a/lib/lp/code/feed/branch.py b/lib/lp/code/feed/branch.py
index 3339134..27d2047 100644
--- a/lib/lp/code/feed/branch.py
+++ b/lib/lp/code/feed/branch.py
@@ -67,7 +67,7 @@ class BranchFeedContentView(BranchView):
 
     def __init__(self, context, request, feed,
                  template='templates/branch.pt'):
-        super(BranchFeedContentView, self).__init__(context, request)
+        super().__init__(context, request)
         self.feed = feed
         self.template_ = template
 
@@ -196,7 +196,7 @@ class RevisionFeedContentView(LaunchpadView):
     """View for a revision feed contents."""
 
     def __init__(self, context, request, feed):
-        super(RevisionFeedContentView, self).__init__(context, request)
+        super().__init__(context, request)
         self.feed = feed
 
     @cachedproperty
@@ -391,7 +391,7 @@ class BranchFeed(BranchFeedBase):
     def initialize(self):
         """See `IFeed`."""
         # For a `BranchFeed` we must ensure that the branch is not private.
-        super(BranchFeed, self).initialize()
+        super().initialize()
         try:
             feed_allowed = not self.context.private
             if not feed_allowed:
diff --git a/lib/lp/code/interfaces/branch.py b/lib/lp/code/interfaces/branch.py
index e6d4e14..57d63e4 100644
--- a/lib/lp/code/interfaces/branch.py
+++ b/lib/lp/code/interfaces/branch.py
@@ -281,7 +281,7 @@ class IBranchView(IHasOwner, IHasBranchTarget, IHasMergeProposals,
     id = Int(title=_('ID'), readonly=True, required=True)
 
     @operation_parameters(
-        scheme=TextLine(title=_("URL scheme"), default=u'http'))
+        scheme=TextLine(title=_("URL scheme"), default='http'))
     @export_read_operation()
     @operation_for_version('beta')
     def composePublicURL(scheme='http'):
@@ -1376,11 +1376,11 @@ class IBranchSet(Interface):
 
     @operation_parameters(
         urls=List(
-            title=u'A list of URLs of branches',
+            title='A list of URLs of branches',
             description=(
-                u'These can be URLs external to '
-                u'Launchpad, lp: URLs, or http://bazaar.launchpad.net/ URLs, '
-                u'or any mix of all these different kinds.'),
+                'These can be URLs external to '
+                'Launchpad, lp: URLs, or http://bazaar.launchpad.net/ URLs, '
+                'or any mix of all these different kinds.'),
             value_type=TextLine(),
             required=True))
     @export_read_operation()
diff --git a/lib/lp/code/interfaces/branchjob.py b/lib/lp/code/interfaces/branchjob.py
index 6ab861e..4f14416 100644
--- a/lib/lp/code/interfaces/branchjob.py
+++ b/lib/lp/code/interfaces/branchjob.py
@@ -91,13 +91,13 @@ class IBranchUpgradeJobSource(IJobSource):
 class IRevisionMailJob(IRunnableJob):
     """A Job to send email a revision change in a branch."""
 
-    revno = Int(title=u'The revno to send mail about.')
+    revno = Int(title='The revno to send mail about.')
 
-    from_address = Bytes(title=u'The address to send mail from.')
+    from_address = Bytes(title='The address to send mail from.')
 
-    body = Text(title=u'The main text of the email to send.')
+    body = Text(title='The main text of the email to send.')
 
-    subject = Text(title=u'The subject of the email to send.')
+    subject = Text(title='The subject of the email to send.')
 
 
 class IRevisionMailJobSource(IJobSource):
diff --git a/lib/lp/code/interfaces/codeimport.py b/lib/lp/code/interfaces/codeimport.py
index 7799e90..1a3e5a1 100644
--- a/lib/lp/code/interfaces/codeimport.py
+++ b/lib/lp/code/interfaces/codeimport.py
@@ -55,7 +55,7 @@ class CVSRootError(Exception):
     """Raised when trying to use a CVSROOT with invalid syntax."""
 
     def __init__(self, root):
-        super(CVSRootError, self).__init__(self, 'bad CVSROOT: %r' % root)
+        super().__init__(self, 'bad CVSROOT: %r' % root)
 
 
 _cvs_root_parser = re.compile(r"""
diff --git a/lib/lp/code/interfaces/gitrepository.py b/lib/lp/code/interfaces/gitrepository.py
index aae1b90..d2d6a90 100644
--- a/lib/lp/code/interfaces/gitrepository.py
+++ b/lib/lp/code/interfaces/gitrepository.py
@@ -832,7 +832,7 @@ class RevisionStatusReportsFeatureDisabled(Unauthorized):
     """Only certain users can access APIs for revision status reports."""
 
     def __init__(self):
-        super(RevisionStatusReportsFeatureDisabled, self).__init__(
+        super().__init__(
             "You do not have permission to create revision status reports")
 
 
diff --git a/lib/lp/code/interfaces/sourcepackagerecipe.py b/lib/lp/code/interfaces/sourcepackagerecipe.py
index f954618..af05f7b 100644
--- a/lib/lp/code/interfaces/sourcepackagerecipe.py
+++ b/lib/lp/code/interfaces/sourcepackagerecipe.py
@@ -69,13 +69,13 @@ from lp.services.fields import (
 from lp.soyuz.interfaces.archive import IArchive
 
 
-MINIMAL_RECIPE_TEXT_BZR = dedent(u'''\
+MINIMAL_RECIPE_TEXT_BZR = dedent('''\
     # bzr-builder format 0.3 deb-version {debupstream}-0~{revno}
     %s
     ''')
 
 
-MINIMAL_RECIPE_TEXT_GIT = dedent(u'''\
+MINIMAL_RECIPE_TEXT_GIT = dedent('''\
     # git-build-recipe format 0.4 deb-version {debupstream}-0~{revtime}
     %s %s
     ''')
diff --git a/lib/lp/code/mail/branch.py b/lib/lp/code/mail/branch.py
index c36a8b7..5de23f2 100644
--- a/lib/lp/code/mail/branch.py
+++ b/lib/lp/code/mail/branch.py
@@ -58,8 +58,7 @@ class RecipientReason(basemailer.RecipientReason):
                  max_diff_lines=BranchSubscriptionDiffSize.WHOLEDIFF,
                  branch_identity_cache=None,
                  review_level=CodeReviewNotificationLevel.FULL):
-        super(RecipientReason, self).__init__(subscriber, recipient,
-              mail_header, reason_template)
+        super().__init__(subscriber, recipient, mail_header, reason_template)
         self.branch = branch
         self.merge_proposal = merge_proposal
         self.max_diff_lines = max_diff_lines
@@ -150,7 +149,7 @@ class RecipientReason(basemailer.RecipientReason):
                      branch_identity_cache=branch_identity_cache)
 
     def _getTemplateValues(self):
-        template_values = super(RecipientReason, self)._getTemplateValues()
+        template_values = super()._getTemplateValues()
         template_values['branch_name'] = self._getBranchIdentity(self.branch)
         if self.merge_proposal is not None:
             source = self._getBranchIdentity(self.merge_proposal.merge_source)
@@ -169,7 +168,7 @@ class BranchMailer(BaseMailer):
                  delta=None, delta_for_editors=None, contents=None, diff=None,
                  message_id=None, revno=None, revision_id=None,
                  notification_type=None, **kwargs):
-        super(BranchMailer, self).__init__(
+        super().__init__(
             subject, template_name, recipients, from_address,
             message_id=message_id, notification_type=notification_type)
         self.delta_text = delta
diff --git a/lib/lp/code/mail/sourcepackagerecipebuild.py b/lib/lp/code/mail/sourcepackagerecipebuild.py
index 5b81714..a12452e 100644
--- a/lib/lp/code/mail/sourcepackagerecipebuild.py
+++ b/lib/lp/code/mail/sourcepackagerecipebuild.py
@@ -42,8 +42,7 @@ class SourcePackageRecipeBuildMailer(BaseMailer):
 
     def _getHeaders(self, email, recipient):
         """See `BaseMailer`"""
-        headers = super(
-            SourcePackageRecipeBuildMailer, self)._getHeaders(email, recipient)
+        headers = super()._getHeaders(email, recipient)
         headers.update({
             'X-Launchpad-Archive': self.build.archive.reference,
             'X-Launchpad-Build-State': self.build.status.name,
@@ -52,9 +51,7 @@ class SourcePackageRecipeBuildMailer(BaseMailer):
 
     def _getTemplateParams(self, email, recipient):
         """See `BaseMailer`"""
-        params = super(
-            SourcePackageRecipeBuildMailer, self)._getTemplateParams(
-                email, recipient)
+        params = super()._getTemplateParams(email, recipient)
         params.update({
             'status': self.build.status.title,
             'build_id': self.build.id,
diff --git a/lib/lp/code/mail/tests/test_branch.py b/lib/lp/code/mail/tests/test_branch.py
index 69ed7dd..ee56593 100644
--- a/lib/lp/code/mail/tests/test_branch.py
+++ b/lib/lp/code/mail/tests/test_branch.py
@@ -306,7 +306,7 @@ class TestBranchMailerDiffMixin:
 
     def test_generateEmail_with_diff(self):
         """When there is a diff, it should be an attachment, not inline."""
-        ctrl = self.makeBobMailController(diff=u'hello \u03A3')
+        ctrl = self.makeBobMailController(diff='hello \u03A3')
         self.assertEqual(1, len(ctrl.attachments))
         diff = ctrl.attachments[0]
         self.assertEqual(b'hello \xce\xa3', diff.get_payload(decode=True))
diff --git a/lib/lp/code/mail/tests/test_branchmergeproposal.py b/lib/lp/code/mail/tests/test_branchmergeproposal.py
index 537918f..8e1e6f7 100644
--- a/lib/lp/code/mail/tests/test_branchmergeproposal.py
+++ b/lib/lp/code/mail/tests/test_branchmergeproposal.py
@@ -57,7 +57,7 @@ class TestMergeProposalMailing(TestCaseWithFactory):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestMergeProposalMailing, self).setUp('admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
 
     def makeProposalWithSubscriber(self, diff_text=None, initial_comment=None,
                                    prerequisite=False, needs_review=True,
diff --git a/lib/lp/code/mail/tests/test_codehandler.py b/lib/lp/code/mail/tests/test_codehandler.py
index 21f8256..4788904 100644
--- a/lib/lp/code/mail/tests/test_codehandler.py
+++ b/lib/lp/code/mail/tests/test_codehandler.py
@@ -129,13 +129,13 @@ class TestCodeHandler(TestCaseWithFactory):
     layer = ZopelessAppServerLayer
 
     def setUp(self):
-        super(TestCodeHandler, self).setUp(user='test@xxxxxxxxxxxxx')
+        super().setUp(user='test@xxxxxxxxxxxxx')
         self.code_handler = CodeHandler()
         self._old_policy = setSecurityPolicy(LaunchpadSecurityPolicy)
 
     def tearDown(self):
         setSecurityPolicy(self._old_policy)
-        super(TestCodeHandler, self).tearDown()
+        super().tearDown()
 
     def test_get(self):
         handler = mail_handlers.get(config.launchpad.code_domain)
@@ -453,7 +453,7 @@ class TestVoteEmailCommand(TestCase):
     # We don't need no stinking layer.
 
     def setUp(self):
-        super(TestVoteEmailCommand, self).setUp()
+        super().setUp()
 
         class FakeExecutionContext:
             vote = None
@@ -555,8 +555,7 @@ class TestUpdateStatusEmailCommand(TestCaseWithFactory):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestUpdateStatusEmailCommand, self).setUp(
-            user='test@xxxxxxxxxxxxx')
+        super().setUp(user='test@xxxxxxxxxxxxx')
         self._old_policy = setSecurityPolicy(LaunchpadSecurityPolicy)
         self.merge_proposal = self.factory.makeBranchMergeProposal()
         # Default the user to be the target branch owner, so they are
@@ -568,7 +567,7 @@ class TestUpdateStatusEmailCommand(TestCaseWithFactory):
 
     def tearDown(self):
         setSecurityPolicy(self._old_policy)
-        super(TestUpdateStatusEmailCommand, self).tearDown()
+        super().tearDown()
 
     def test_numberOfArguments(self):
         # The command needs one and only one arg.
@@ -678,8 +677,7 @@ class TestAddReviewerEmailCommand(TestCaseWithFactory):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestAddReviewerEmailCommand, self).setUp(
-            user='test@xxxxxxxxxxxxx')
+        super().setUp(user='test@xxxxxxxxxxxxx')
         self._old_policy = setSecurityPolicy(LaunchpadSecurityPolicy)
         self.merge_proposal = (
             make_merge_proposal_without_reviewers(self.factory))
@@ -692,7 +690,7 @@ class TestAddReviewerEmailCommand(TestCaseWithFactory):
 
     def tearDown(self):
         setSecurityPolicy(self._old_policy)
-        super(TestAddReviewerEmailCommand, self).tearDown()
+        super().tearDown()
 
     def test_numberOfArguments(self):
         # The command needs at least one arg.
diff --git a/lib/lp/code/mail/tests/test_codeimport.py b/lib/lp/code/mail/tests/test_codeimport.py
index ee62761..77eefa5 100644
--- a/lib/lp/code/mail/tests/test_codeimport.py
+++ b/lib/lp/code/mail/tests/test_codeimport.py
@@ -110,7 +110,7 @@ class TestNewCodeImports(TestCaseWithFactory):
         login_person(eric)
         self.factory.makeProductCodeImport(
             git_repo_url='git://git.example.com/fooix.git',
-            branch_name=u'master', product=fooix, registrant=eric,
+            branch_name='master', product=fooix, registrant=eric,
             target_rcs_type=TargetRevisionControlSystems.GIT)
         transaction.commit()
         msg = email.message_from_bytes(stub.test_emails[0][2])
diff --git a/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py b/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py
index b0f8f25..ed194e3 100644
--- a/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py
+++ b/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py
@@ -16,7 +16,7 @@ from lp.testing.dbuser import switch_dbuser
 from lp.testing.layers import LaunchpadZopelessLayer
 
 
-expected_body = u"""\
+expected_body = """\
  * State: Successfully built
  * Recipe: person/recipe
  * Archive: ~archiveowner/ubuntu/ppa
@@ -27,7 +27,7 @@ expected_body = u"""\
  * Builder: http://launchpad.test/builders/bob
 """  # noqa: W291
 
-superseded_body = u"""\
+superseded_body = """\
  * State: Build for superseded Source
  * Recipe: person/recipe
  * Archive: ~archiveowner/ubuntu/ppa
@@ -53,10 +53,10 @@ class TestSourcePackageRecipeBuildMailer(TestCaseWithFactory):
         """GenerateEmail produces the right headers and body."""
         person = self.factory.makePerson(name='person')
         cake = self.factory.makeSourcePackageRecipe(
-            name=u'recipe', owner=person)
+            name='recipe', owner=person)
         pantry_owner = self.factory.makePerson(name='archiveowner')
         pantry = self.factory.makeArchive(name='ppa', owner=pantry_owner)
-        secret = self.factory.makeDistroSeries(name=u'distroseries')
+        secret = self.factory.makeDistroSeries(name='distroseries')
         secret.nominatedarchindep = (
             self.factory.makeDistroArchSeries(distroseries=secret))
         build = self.factory.makeSourcePackageRecipeBuild(
@@ -64,11 +64,11 @@ class TestSourcePackageRecipeBuildMailer(TestCaseWithFactory):
             status=BuildStatus.FULLYBUILT, duration=timedelta(minutes=5))
         build.updateStatus(
             BuildStatus.FULLYBUILT,
-            builder=self.factory.makeBuilder(name=u'bob'))
+            builder=self.factory.makeBuilder(name='bob'))
         build.setLog(self.factory.makeLibraryFileAlias())
         ctrl = self.makeStatusEmail(build)
         self.assertEqual(
-            u'[recipe build #%d] of ~person recipe in distroseries: '
+            '[recipe build #%d] of ~person recipe in distroseries: '
             'Successfully built' % (build.id), ctrl.subject)
         body, footer = ctrl.body.split('\n-- \n')
         self.assertEqual(expected_body % build.log_url, body)
@@ -93,10 +93,10 @@ class TestSourcePackageRecipeBuildMailer(TestCaseWithFactory):
         """GenerateEmail works when many fields are NULL."""
         person = self.factory.makePerson(name='person')
         cake = self.factory.makeSourcePackageRecipe(
-            name=u'recipe', owner=person)
+            name='recipe', owner=person)
         pantry_owner = self.factory.makePerson(name='archiveowner')
         pantry = self.factory.makeArchive(name='ppa', owner=pantry_owner)
-        secret = self.factory.makeDistroSeries(name=u'distroseries')
+        secret = self.factory.makeDistroSeries(name='distroseries')
         secret.nominatedarchindep = (
             self.factory.makeDistroArchSeries(distroseries=secret))
         build = self.factory.makeSourcePackageRecipeBuild(
@@ -105,7 +105,7 @@ class TestSourcePackageRecipeBuildMailer(TestCaseWithFactory):
         Store.of(build).flush()
         ctrl = self.makeStatusEmail(build)
         self.assertEqual(
-            u'[recipe build #%d] of ~person recipe in distroseries: '
+            '[recipe build #%d] of ~person recipe in distroseries: '
             'Build for superseded Source' % (build.id), ctrl.subject)
         body, footer = ctrl.body.split('\n-- \n')
         self.assertEqual(superseded_body, body)
diff --git a/lib/lp/code/model/branch.py b/lib/lp/code/model/branch.py
index 1a9bcc4..98952be 100644
--- a/lib/lp/code/model/branch.py
+++ b/lib/lp/code/model/branch.py
@@ -811,7 +811,7 @@ class Branch(SQLBase, WebhookTargetMixin, BzrIdentityMixin):
         hosting_client = getUtility(IBranchHostingClient)
         if enable_memcache is None:
             enable_memcache = not getFeatureFlag(
-                u'code.bzr.blob.disable_memcache')
+                'code.bzr.blob.disable_memcache')
         if revision_id is None:
             revision_id = self.last_scanned_id
         if revision_id is None:
@@ -1138,7 +1138,7 @@ class Branch(SQLBase, WebhookTargetMixin, BzrIdentityMixin):
 
     def removeBranchRevisions(self, revision_ids):
         """See `IBranch`."""
-        if isinstance(revision_ids, six.string_types):
+        if isinstance(revision_ids, str):
             revision_ids = [revision_ids]
         IMasterStore(BranchRevision).find(
             BranchRevision,
diff --git a/lib/lp/code/model/branchcollection.py b/lib/lp/code/model/branchcollection.py
index 6ba75ec..fe27bc6 100644
--- a/lib/lp/code/model/branchcollection.py
+++ b/lib/lp/code/model/branchcollection.py
@@ -562,7 +562,7 @@ class GenericBranchCollection:
                 bugtasks_for_branch[bugbranch.branch].append(bugtask)
 
             # Now filter those down to one bugtask per branch
-            for branch, tasks in six.iteritems(bugtasks_for_branch):
+            for branch, tasks in bugtasks_for_branch.items():
                 linked_bugtasks[branch.id].extend(
                     filter_bugtasks_by_context(branch.target.context, tasks))
 
@@ -786,7 +786,7 @@ class VisibleBranchCollection(GenericBranchCollection):
     def __init__(self, user, store=None, branch_filter_expressions=None,
                  tables=None,
                  asymmetric_filter_expressions=None, asymmetric_tables=None):
-        super(VisibleBranchCollection, self).__init__(
+        super().__init__(
             store=store, branch_filter_expressions=branch_filter_expressions,
             tables=tables,
             asymmetric_filter_expressions=asymmetric_filter_expressions,
diff --git a/lib/lp/code/model/branchhosting.py b/lib/lp/code/model/branchhosting.py
index 58594e3..3911c16 100644
--- a/lib/lp/code/model/branchhosting.py
+++ b/lib/lp/code/model/branchhosting.py
@@ -12,7 +12,6 @@ import sys
 
 from lazr.restful.utils import get_current_browser_request
 import requests
-from six import reraise
 from six.moves.urllib_parse import (
     quote,
     urljoin,
@@ -72,9 +71,7 @@ class BranchHostingClient:
         except Exception:
             _, val, tb = sys.exc_info()
             try:
-                reraise(
-                    RequestExceptionWrapper,
-                    RequestExceptionWrapper(*val.args), tb)
+                raise RequestExceptionWrapper(*val.args).with_traceback(tb)
             finally:
                 # Avoid traceback reference cycles.
                 del val, tb
diff --git a/lib/lp/code/model/branchjob.py b/lib/lp/code/model/branchjob.py
index 5d7c0d8..aa06aeb 100644
--- a/lib/lp/code/model/branchjob.py
+++ b/lib/lp/code/model/branchjob.py
@@ -227,7 +227,7 @@ class BranchJob(StormBase):
         :param metadata: The type-specific variables, as a JSON-compatible
             dict.
         """
-        super(BranchJob, self).__init__()
+        super().__init__()
         self.job = Job(**job_args)
         self.branch = branch
         self.job_type = job_type
@@ -329,7 +329,7 @@ class BranchScanJob(BranchJobDerived):
         return cls(branch_job)
 
     def __init__(self, branch_job):
-        super(BranchScanJob, self).__init__(branch_job)
+        super().__init__(branch_job)
         self._cached_branch_name = self.metadata['branch_name']
 
     @staticmethod
@@ -507,7 +507,7 @@ class RevisionsAddedJob(BranchJobDerived):
         return RevisionsAddedJob(branch_job)
 
     def __init__(self, context):
-        super(RevisionsAddedJob, self).__init__(context)
+        super().__init__(context)
         self._bzr_branch = None
         self._tree_cache = {}
 
@@ -690,7 +690,7 @@ class RevisionsAddedJob(BranchJobDerived):
                 proposals[source_id] = (proposal, date_created)
 
         return sorted(
-            (proposal for proposal, date_created in six.itervalues(proposals)),
+            (proposal for proposal, date_created in proposals.values()),
             key=operator.attrgetter('date_created'), reverse=True)
 
     def getRevisionMessage(self, revision_id, revno):
@@ -763,7 +763,7 @@ class RosettaUploadJob(BranchJobDerived):
     config = config.IRosettaUploadJobSource
 
     def __init__(self, branch_job):
-        super(RosettaUploadJob, self).__init__(branch_job)
+        super().__init__(branch_job)
 
         self.template_file_names = []
         self.template_files_changed = []
diff --git a/lib/lp/code/model/branchmergeproposal.py b/lib/lp/code/model/branchmergeproposal.py
index a0ff7d1..f0f23d7 100644
--- a/lib/lp/code/model/branchmergeproposal.py
+++ b/lib/lp/code/model/branchmergeproposal.py
@@ -18,7 +18,6 @@ from lazr.lifecycle.event import (
     ObjectCreatedEvent,
     ObjectDeletedEvent,
     )
-import six
 from storm.expr import (
     And,
     Desc,
@@ -392,8 +391,7 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin):
         else:
             bug_ids = [
                 int(id) for _, id in getUtility(IXRefSet).findFrom(
-                    (u'merge_proposal', six.text_type(self.id)),
-                    types=[u'bug'])]
+                    ('merge_proposal', str(self.id)), types=['bug'])]
             bugs = load(Bug, bug_ids)
         return list(sorted(bugs, key=attrgetter('id')))
 
@@ -420,14 +418,12 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin):
             props = {}
         # XXX cjwatson 2016-06-11: Should set creator.
         getUtility(IXRefSet).create(
-            {(u'merge_proposal', six.text_type(self.id)):
-                {(u'bug', six.text_type(bug.id)): props}})
+            {('merge_proposal', str(self.id)): {('bug', str(bug.id)): props}})
 
     def deleteBugLink(self, bug):
         """See `BugLinkTargetMixin`."""
         getUtility(IXRefSet).delete(
-            {(u'merge_proposal', six.text_type(self.id)):
-                [(u'bug', six.text_type(bug.id))]})
+            {('merge_proposal', str(self.id)): [('bug', str(bug.id))]})
 
     def linkBug(self, bug, user=None, check_permissions=True, props=None):
         """See `BugLinkTargetMixin`."""
@@ -436,7 +432,7 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin):
             return self.source_branch.linkBug(bug, user)
         else:
             # Otherwise, link the bug to the merge proposal directly.
-            return super(BranchMergeProposal, self).linkBug(
+            return super().linkBug(
                 bug, user=user, check_permissions=check_permissions,
                 props=props)
 
@@ -451,7 +447,7 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin):
             return self.source_branch.unlinkBug(bug, user)
         else:
             # Otherwise, unlink the bug from the merge proposal directly.
-            return super(BranchMergeProposal, self).unlinkBug(
+            return super().unlinkBug(
                 bug, user=user, check_permissions=check_permissions)
 
     def _reportTooManyRelatedBugs(self):
@@ -505,8 +501,7 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin):
         current_bug_ids_from_source = {
             int(id): (props['metadata'] or {}).get('from_source', False)
             for (_, id), props in getUtility(IXRefSet).findFrom(
-                (u'merge_proposal', six.text_type(self.id)),
-                types=[u'bug']).items()}
+                ('merge_proposal', str(self.id)), types=['bug']).items()}
         current_bug_ids = set(current_bug_ids_from_source)
         new_bug_ids = self._fetchRelatedBugIDsFromSource()
         # Only remove links marked as originating in the source branch.
diff --git a/lib/lp/code/model/branchmergeproposaljob.py b/lib/lp/code/model/branchmergeproposaljob.py
index 3a58ae9..8c1fd83 100644
--- a/lib/lp/code/model/branchmergeproposaljob.py
+++ b/lib/lp/code/model/branchmergeproposaljob.py
@@ -175,7 +175,7 @@ class BranchMergeProposalJob(StormBase):
         :param metadata: The type-specific variables, as a JSON-compatible
             dict.
         """
-        super(BranchMergeProposalJob, self).__init__()
+        super().__init__()
         json_data = simplejson.dumps(metadata)
         self.job = Job()
         self.branch_merge_proposal = branch_merge_proposal
diff --git a/lib/lp/code/model/branchsubscription.py b/lib/lp/code/model/branchsubscription.py
index c9b10a8..36ec00a 100644
--- a/lib/lp/code/model/branchsubscription.py
+++ b/lib/lp/code/model/branchsubscription.py
@@ -48,7 +48,7 @@ class BranchSubscription(StormBase):
 
     def __init__(self, person, branch, notification_level, max_diff_lines,
                  review_level, subscribed_by):
-        super(BranchSubscription, self).__init__()
+        super().__init__()
         self.person = person
         self.branch = branch
         self.notification_level = notification_level
diff --git a/lib/lp/code/model/branchtarget.py b/lib/lp/code/model/branchtarget.py
index 9100558..f341171 100644
--- a/lib/lp/code/model/branchtarget.py
+++ b/lib/lp/code/model/branchtarget.py
@@ -187,7 +187,7 @@ class PackageBranchTarget(_BaseBranchTarget):
 @implementer(IBranchTarget)
 class PersonBranchTarget(_BaseBranchTarget):
 
-    name = u'+junk'
+    name = '+junk'
     default_stacked_on_branch = None
     default_merge_target = None
 
diff --git a/lib/lp/code/model/codeimport.py b/lib/lp/code/model/codeimport.py
index c2b028e..13f6559 100644
--- a/lib/lp/code/model/codeimport.py
+++ b/lib/lp/code/model/codeimport.py
@@ -83,7 +83,7 @@ class CodeImport(StormBase):
 
     def __init__(self, registrant, owner, target, review_status, rcs_type=None,
                  url=None, cvs_root=None, cvs_module=None):
-        super(CodeImport, self).__init__()
+        super().__init__()
         self.registrant = registrant
         self.owner = owner
         if IBranch.providedBy(target):
diff --git a/lib/lp/code/model/codeimportevent.py b/lib/lp/code/model/codeimportevent.py
index eb399d1..2b41ce4 100644
--- a/lib/lp/code/model/codeimportevent.py
+++ b/lib/lp/code/model/codeimportevent.py
@@ -12,7 +12,6 @@ __all__ = [
 
 from lazr.enum import DBItem
 import pytz
-import six
 from storm.locals import (
     DateTime,
     Int,
@@ -65,7 +64,7 @@ class CodeImportEvent(StormBase):
 
     def __init__(self, event_type, code_import=None, person=None,
                  machine=None, date_created=DEFAULT):
-        super(CodeImportEvent, self).__init__()
+        super().__init__()
         self.event_type = event_type
         self.code_import = code_import
         self.person = person
@@ -97,7 +96,7 @@ class _CodeImportEventData(StormBase):
     data_value = Unicode(allow_none=True)
 
     def __init__(self, event, data_type, data_value):
-        super(_CodeImportEventData, self).__init__()
+        super().__init__()
         self.event = event
         self.data_type = data_type
         self.data_value = data_value
@@ -200,7 +199,7 @@ class CodeImportEventSet:
         IStore(CodeImportEvent).add(event)
         IStore(_CodeImportEventData).add(_CodeImportEventData(
             event=event, data_type=CodeImportEventDataType.OFFLINE_REASON,
-            data_value=six.text_type(reason.name)))
+            data_value=str(reason.name)))
         self._recordMessage(event, message)
         return event
 
@@ -257,7 +256,7 @@ class CodeImportEventSet:
         IStore(CodeImportEvent).add(event)
         IStore(_CodeImportEventData).add(_CodeImportEventData(
             event=event, data_type=CodeImportEventDataType.RECLAIMED_JOB_ID,
-            data_value=six.text_type(job_id)))
+            data_value=str(job_id)))
         return event
 
     def _recordSnapshot(self, event, code_import):
@@ -278,18 +277,17 @@ class CodeImportEventSet:
     def _iterItemsForSnapshot(self, code_import):
         """Yield key-value tuples to save a snapshot of the code import."""
         yield self._getCodeImportItem(code_import)
-        yield 'REVIEW_STATUS', six.text_type(code_import.review_status.name)
-        yield 'OWNER', six.text_type(code_import.owner.id)
+        yield 'REVIEW_STATUS', str(code_import.review_status.name)
+        yield 'OWNER', str(code_import.owner.id)
         yield 'UPDATE_INTERVAL', self._getNullableValue(
             code_import.update_interval)
         yield 'ASSIGNEE', self._getNullableValue(
             code_import.assignee, use_id=True)
-        for detail in self._iterSourceDetails(code_import):
-            yield detail
+        yield from self._iterSourceDetails(code_import)
 
     def _getCodeImportItem(self, code_import):
         """Return the key-value tuple for the code import id."""
-        return 'CODE_IMPORT', six.text_type(code_import.id)
+        return 'CODE_IMPORT', str(code_import.id)
 
     def _getNullableValue(self, value, use_id=False):
         """Return the string value for a nullable value.
@@ -301,9 +299,9 @@ class CodeImportEventSet:
         if value is None:
             return None
         elif use_id:
-            return six.text_type(value.id)
+            return str(value.id)
         else:
-            return six.text_type(value)
+            return str(value)
 
     def _iterSourceDetails(self, code_import):
         """Yield key-value tuples describing the source of the import."""
diff --git a/lib/lp/code/model/codeimportjob.py b/lib/lp/code/model/codeimportjob.py
index a7839a3..0d010c5 100644
--- a/lib/lp/code/model/codeimportjob.py
+++ b/lib/lp/code/model/codeimportjob.py
@@ -104,7 +104,7 @@ class CodeImportJob(StormBase):
     date_started = DateTime(tzinfo=pytz.UTC, allow_none=True, default=None)
 
     def __init__(self, code_import, date_due):
-        super(CodeImportJob, self).__init__()
+        super().__init__()
         self.code_import = code_import
         self.date_due = date_due
 
@@ -179,7 +179,7 @@ class CodeImportJob(StormBase):
 
 
 @implementer(ICodeImportJobSet, ICodeImportJobSetPublic)
-class CodeImportJobSet(object):
+class CodeImportJobSet:
     """See `ICodeImportJobSet`."""
 
     # CodeImportJob database objects are created using
diff --git a/lib/lp/code/model/codeimportmachine.py b/lib/lp/code/model/codeimportmachine.py
index 084f8ca..0ce2fc5 100644
--- a/lib/lp/code/model/codeimportmachine.py
+++ b/lib/lp/code/model/codeimportmachine.py
@@ -65,7 +65,7 @@ class CodeImportMachine(StormBase):
             Desc('CodeImportEvent.id')))
 
     def __init__(self, hostname, heartbeat=None):
-        super(CodeImportMachine, self).__init__()
+        super().__init__()
         self.hostname = hostname
         self.heartbeat = heartbeat
         self.state = CodeImportMachineState.OFFLINE
@@ -120,7 +120,7 @@ class CodeImportMachine(StormBase):
 
 
 @implementer(ICodeImportMachineSet)
-class CodeImportMachineSet(object):
+class CodeImportMachineSet:
     """See `ICodeImportMachineSet`."""
 
     def getAll(self):
diff --git a/lib/lp/code/model/codeimportresult.py b/lib/lp/code/model/codeimportresult.py
index 84fb963..222e3d6 100644
--- a/lib/lp/code/model/codeimportresult.py
+++ b/lib/lp/code/model/codeimportresult.py
@@ -59,7 +59,7 @@ class CodeImportResult(StormBase):
     def __init__(self, code_import, machine, status, date_job_started,
                  requesting_user=None, log_excerpt=None, log_file=None,
                  date_created=UTC_NOW):
-        super(CodeImportResult, self).__init__()
+        super().__init__()
         self.code_import = code_import
         self.machine = machine
         self.status = status
@@ -80,7 +80,7 @@ class CodeImportResult(StormBase):
 
 
 @implementer(ICodeImportResultSet)
-class CodeImportResultSet(object):
+class CodeImportResultSet:
     """See `ICodeImportResultSet`."""
 
     def new(self, code_import, machine, requesting_user, log_excerpt,
diff --git a/lib/lp/code/model/codereviewinlinecomment.py b/lib/lp/code/model/codereviewinlinecomment.py
index a6dc6da..a86d682 100644
--- a/lib/lp/code/model/codereviewinlinecomment.py
+++ b/lib/lp/code/model/codereviewinlinecomment.py
@@ -9,7 +9,6 @@ __all__ = [
     'CodeReviewInlineCommentSet',
     ]
 
-import six
 from storm.expr import LeftJoin
 from storm.locals import (
     Int,
@@ -113,7 +112,7 @@ class CodeReviewInlineCommentSet:
             list(crics), key=lambda c: c.comment.date_created)
         inline_comments = []
         for cric in sorted_crics:
-            for line_number, text in six.iteritems(cric.comments):
+            for line_number, text in cric.comments.items():
                 comment = {
                     'line_number': line_number,
                     'person': cric.person,
diff --git a/lib/lp/code/model/diff.py b/lib/lp/code/model/diff.py
index 13f633c..93626b2 100644
--- a/lib/lp/code/model/diff.py
+++ b/lib/lp/code/model/diff.py
@@ -98,7 +98,7 @@ class Diff(SQLBase):
     @property
     def text(self):
         if self.diff_text is None:
-            return u''
+            return ''
         else:
             with reduced_timeout(
                     0.01, webapp_max=2.0,
@@ -385,13 +385,13 @@ class PreviewDiff(Storm):
             source_revision = bmp.source_branch.getBranchRevision(
                 revision_id=self.source_revision_id)
             if source_revision and source_revision.sequence:
-                source_rev = u'r{}'.format(source_revision.sequence)
+                source_rev = 'r{}'.format(source_revision.sequence)
             else:
                 source_rev = self.source_revision_id
             target_revision = bmp.target_branch.getBranchRevision(
                 revision_id=self.target_revision_id)
             if target_revision and target_revision.sequence:
-                target_rev = u'r{}'.format(target_revision.sequence)
+                target_rev = 'r{}'.format(target_revision.sequence)
             else:
                 target_rev = self.target_revision_id
         else:
@@ -402,7 +402,7 @@ class PreviewDiff(Storm):
             source_rev = self.source_revision_id[:7]
             target_rev = self.target_revision_id[:7]
 
-        return u'{} into {}'.format(source_rev, target_rev)
+        return '{} into {}'.format(source_rev, target_rev)
 
     @property
     def has_conflicts(self):
@@ -433,8 +433,8 @@ class PreviewDiff(Storm):
             preview.target_revision_id = target_revision.decode('utf-8')
             preview.branch_merge_proposal = bmp
             preview.diff = diff
-            preview.conflicts = u''.join(
-                six.text_type(conflict) + '\n' for conflict in conflicts)
+            preview.conflicts = ''.join(
+                str(conflict) + '\n' for conflict in conflicts)
         else:
             source_repository = bmp.source_git_repository
             target_repository = bmp.target_git_repository
@@ -449,8 +449,8 @@ class PreviewDiff(Storm):
             response = getUtility(IGitHostingClient).getMergeDiff(
                 path, bmp.target_git_commit_sha1, bmp.source_git_commit_sha1,
                 prerequisite=bmp.prerequisite_git_commit_sha1)
-            conflicts = u"".join(
-                u"Conflict in %s\n" % path for path in response['conflicts'])
+            conflicts = "".join(
+                "Conflict in %s\n" % path for path in response['conflicts'])
             preview = cls.create(
                 bmp, response['patch'].encode('utf-8'),
                 bmp.source_git_commit_sha1, bmp.target_git_commit_sha1,
diff --git a/lib/lp/code/model/gitactivity.py b/lib/lp/code/model/gitactivity.py
index a7b2036..42091f1 100644
--- a/lib/lp/code/model/gitactivity.py
+++ b/lib/lp/code/model/gitactivity.py
@@ -60,7 +60,7 @@ class GitActivity(StormBase):
 
     def __init__(self, repository, changer, what_changed, changee=None,
                  old_value=None, new_value=None, date_changed=DEFAULT):
-        super(GitActivity, self).__init__()
+        super().__init__()
         self.repository = repository
         self.date_changed = date_changed
         self.changer = changer
diff --git a/lib/lp/code/model/gitcollection.py b/lib/lp/code/model/gitcollection.py
index 966ea02..8c2d4f1 100644
--- a/lib/lp/code/model/gitcollection.py
+++ b/lib/lp/code/model/gitcollection.py
@@ -622,7 +622,7 @@ class VisibleGitCollection(GenericGitCollection):
 
     def __init__(self, user, store=None, filter_expressions=None, tables=None,
                  asymmetric_filter_expressions=None, asymmetric_tables=None):
-        super(VisibleGitCollection, self).__init__(
+        super().__init__(
             store=store, filter_expressions=filter_expressions, tables=tables,
             asymmetric_filter_expressions=asymmetric_filter_expressions,
             asymmetric_tables=asymmetric_tables)
diff --git a/lib/lp/code/model/githosting.py b/lib/lp/code/model/githosting.py
index 6494390..e498138 100644
--- a/lib/lp/code/model/githosting.py
+++ b/lib/lp/code/model/githosting.py
@@ -14,11 +14,7 @@ import sys
 
 from lazr.restful.utils import get_current_browser_request
 import requests
-import six
-from six import (
-    ensure_text,
-    reraise,
-    )
+from six import ensure_text
 from six.moves.urllib.parse import (
     quote,
     urljoin,
@@ -89,9 +85,7 @@ class GitHostingClient:
         except Exception:
             _, val, tb = sys.exc_info()
             try:
-                reraise(
-                    RequestExceptionWrapper,
-                    RequestExceptionWrapper(*val.args), tb)
+                raise RequestExceptionWrapper(*val.args).with_traceback(tb)
             finally:
                 # Avoid traceback reference cycles.
                 del val, tb
@@ -131,7 +125,7 @@ class GitHostingClient:
             self._post("/repo", json=request)
         except requests.RequestException as e:
             raise GitRepositoryCreationFault(
-                "Failed to create Git repository: %s" % six.text_type(e), path)
+                "Failed to create Git repository: %s" % str(e), path)
 
     def getProperties(self, path):
         """See `IGitHostingClient`."""
@@ -139,8 +133,7 @@ class GitHostingClient:
             return self._get("/repo/%s" % path)
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to get properties of Git repository: %s" %
-                six.text_type(e))
+                "Failed to get properties of Git repository: %s" % str(e))
 
     def setProperties(self, path, **props):
         """See `IGitHostingClient`."""
@@ -148,8 +141,7 @@ class GitHostingClient:
             self._patch("/repo/%s" % path, json=props)
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to set properties of Git repository: %s" %
-                six.text_type(e))
+                "Failed to set properties of Git repository: %s" % str(e))
 
     def getRefs(self, path, exclude_prefixes=None):
         """See `IGitHostingClient`."""
@@ -159,8 +151,7 @@ class GitHostingClient:
                 params={"exclude_prefix": exclude_prefixes})
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to get refs from Git repository: %s" %
-                six.text_type(e))
+                "Failed to get refs from Git repository: %s" % str(e))
 
     def getCommits(self, path, commit_oids, logger=None):
         """See `IGitHostingClient`."""
@@ -173,7 +164,7 @@ class GitHostingClient:
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
                 "Failed to get commit details from Git repository: %s" %
-                six.text_type(e))
+                str(e))
 
     def getLog(self, path, start, limit=None, stop=None, logger=None):
         """See `IGitHostingClient`."""
@@ -188,8 +179,7 @@ class GitHostingClient:
                 params={"limit": limit, "stop": stop})
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to get commit log from Git repository: %s" %
-                six.text_type(e))
+                "Failed to get commit log from Git repository: %s" % str(e))
 
     def getDiff(self, path, old, new, common_ancestor=False,
                 context_lines=None, logger=None):
@@ -204,8 +194,7 @@ class GitHostingClient:
             return self._get(url, params={"context_lines": context_lines})
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to get diff from Git repository: %s" %
-                six.text_type(e))
+                "Failed to get diff from Git repository: %s" % str(e))
 
     def getMergeDiff(self, path, base, head, prerequisite=None, logger=None):
         """See `IGitHostingClient`."""
@@ -219,8 +208,7 @@ class GitHostingClient:
             return self._get(url, params={"sha1_prerequisite": prerequisite})
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to get merge diff from Git repository: %s" %
-                six.text_type(e))
+                "Failed to get merge diff from Git repository: %s" % str(e))
 
     def detectMerges(self, path, target, sources, logger=None):
         """See `IGitHostingClient`."""
@@ -235,8 +223,7 @@ class GitHostingClient:
                 json={"sources": sources})
         except requests.RequestException as e:
             raise GitRepositoryScanFault(
-                "Failed to detect merges in Git repository: %s" %
-                six.text_type(e))
+                "Failed to detect merges in Git repository: %s" % str(e))
 
     def delete(self, path, logger=None):
         """See `IGitHostingClient`."""
@@ -246,7 +233,7 @@ class GitHostingClient:
             self._delete("/repo/%s" % path)
         except requests.RequestException as e:
             raise GitRepositoryDeletionFault(
-                "Failed to delete Git repository: %s" % six.text_type(e))
+                "Failed to delete Git repository: %s" % str(e))
 
     def getBlob(self, path, filename, rev=None, logger=None):
         """See `IGitHostingClient`."""
@@ -262,8 +249,7 @@ class GitHostingClient:
                 raise GitRepositoryBlobNotFound(path, filename, rev=rev)
             else:
                 raise GitRepositoryScanFault(
-                    "Failed to get file from Git repository: %s" %
-                    six.text_type(e))
+                    "Failed to get file from Git repository: %s" % str(e))
         try:
             blob = base64.b64decode(response["data"].encode("UTF-8"))
             if len(blob) != response["size"]:
@@ -273,8 +259,7 @@ class GitHostingClient:
             return blob
         except Exception as e:
             raise GitRepositoryScanFault(
-                "Failed to get file from Git repository: %s" %
-                six.text_type(e))
+                "Failed to get file from Git repository: %s" % str(e))
 
     def copyRefs(self, path, operations, logger=None):
         """See `IGitHostingClient`."""
@@ -334,7 +319,7 @@ class GitHostingClient:
             else:
                 raise CannotRepackRepository(
                     "Failed to repack Git repository %s: %s" %
-                    (path, six.text_type(e)))
+                    (path, str(e)))
 
     def collectGarbage(self, path, logger=None):
         """See `IGitHostingClient`."""
@@ -349,4 +334,4 @@ class GitHostingClient:
         except requests.RequestException as e:
             raise CannotRunGitGC(
                 "Failed to run Git GC for repository %s: %s" %
-                (path, six.text_type(e)))
+                (path, str(e)))
diff --git a/lib/lp/code/model/gitjob.py b/lib/lp/code/model/gitjob.py
index 2e78d06..8b0ede0 100644
--- a/lib/lp/code/model/gitjob.py
+++ b/lib/lp/code/model/gitjob.py
@@ -125,7 +125,7 @@ class GitJob(StormBase):
         :param metadata: The type-specific variables, as a JSON-compatible
             dict.
         """
-        super(GitJob, self).__init__()
+        super().__init__()
         self.job = Job(**job_args)
         self.repository = repository
         self.job_type = job_type
@@ -177,7 +177,7 @@ class GitJobDerived(BaseRunnableJob, metaclass=EnumeratedSubclass):
 
     def getOopsVars(self):
         """See `IRunnableJob`."""
-        oops_vars = super(GitJobDerived, self).getOopsVars()
+        oops_vars = super().getOopsVars()
         oops_vars.extend([
             ('git_job_id', self.context.job.id),
             ('git_job_type', self.context.job_type.title),
diff --git a/lib/lp/code/model/gitlookup.py b/lib/lp/code/model/gitlookup.py
index 03b5a43..6c5746f 100644
--- a/lib/lp/code/model/gitlookup.py
+++ b/lib/lp/code/model/gitlookup.py
@@ -151,8 +151,7 @@ class ProjectGitTraversable(_BaseGitTraversable):
             if oci_project is None:
                 raise NoSuchOCIProjectName(ociproject_name)
             return owner, oci_project, None
-        return super(ProjectGitTraversable, self).traverse(
-            owner, name, segments)
+        return super().traverse(owner, name, segments)
 
     def getNamespace(self, owner):
         return getUtility(IGitNamespaceSet).get(owner, project=self.context)
@@ -240,8 +239,7 @@ class PersonGitTraversable(_BaseGitTraversable):
             `IGitRepository`).
         """
         if name == "+git":
-            return super(PersonGitTraversable, self).traverse(
-                owner, name, segments)
+            return super().traverse(owner, name, segments)
         else:
             if not valid_name(name):
                 raise InvalidProductName(name)
@@ -266,7 +264,7 @@ class DistributionOCIProjectGitTraversable(_BaseGitTraversable):
             owner, oci_project=self.context)
 
 
-class SegmentIterator(six.Iterator):
+class SegmentIterator:
     """An iterator that remembers the elements it has traversed."""
 
     def __init__(self, iterator):
diff --git a/lib/lp/code/model/gitref.py b/lib/lp/code/model/gitref.py
index 61a7526..11a3959 100644
--- a/lib/lp/code/model/gitref.py
+++ b/lib/lp/code/model/gitref.py
@@ -333,10 +333,10 @@ class GitRefMixin:
                 enable_hosting=None, enable_memcache=None, logger=None):
         if enable_hosting is None:
             enable_hosting = not getFeatureFlag(
-                u"code.git.log.disable_hosting")
+                "code.git.log.disable_hosting")
         if enable_memcache is None:
             enable_memcache = not getFeatureFlag(
-                u"code.git.log.disable_memcache")
+                "code.git.log.disable_memcache")
         path = self.repository.getInternalPath()
         if (union_repository is not None and
                 union_repository != self.repository):
@@ -636,9 +636,9 @@ class GitRef(GitRefMixin, StormBase):
     def findByReposAndPaths(cls, repos_and_paths):
         """See `IGitRefSet`"""
         def full_path(path):
-            if path.startswith(u"refs/heads/"):
+            if path.startswith("refs/heads/"):
                 return path
-            return u"refs/heads/%s" % path
+            return "refs/heads/%s" % path
 
         condition = None
         for repo, path in repos_and_paths:
@@ -702,7 +702,7 @@ class GitRefDefault(GitRefDatabaseBackedMixin):
     def __init__(self, repository):
         self.repository_id = repository.id
         self.repository = repository
-        self.path = u"HEAD"
+        self.path = "HEAD"
 
     _non_database_attributes = ("repository_id", "repository", "path")
 
diff --git a/lib/lp/code/model/gitrepository.py b/lib/lp/code/model/gitrepository.py
index 43a005a..c6b8ada 100644
--- a/lib/lp/code/model/gitrepository.py
+++ b/lib/lp/code/model/gitrepository.py
@@ -500,7 +500,7 @@ class GitRepository(StormBase, WebhookTargetMixin, AccessTokenTargetMixin,
                  description=None, status=None, loose_object_count=None,
                  pack_count=None, date_last_scanned=None,
                  date_last_repacked=None):
-        super(GitRepository, self).__init__()
+        super().__init__()
         self.repository_type = repository_type
         self.registrant = registrant
         self.owner = owner
@@ -798,7 +798,7 @@ class GitRepository(StormBase, WebhookTargetMixin, AccessTokenTargetMixin,
         return Store.of(self).find(
             GitRef,
             GitRef.repository_id == self.id,
-            GitRef.path.startswith(u"refs/heads/")).order_by(GitRef.path)
+            GitRef.path.startswith("refs/heads/")).order_by(GitRef.path)
 
     @property
     def branches_by_date(self):
@@ -831,11 +831,11 @@ class GitRepository(StormBase, WebhookTargetMixin, AccessTokenTargetMixin,
                 self.getInternalPath(), default_branch=ref.path)
 
     def getRefByPath(self, path):
-        if path == u"HEAD":
+        if path == "HEAD":
             return GitRefDefault(self)
         paths = [path]
-        if not path.startswith(u"refs/heads/"):
-            paths.append(u"refs/heads/%s" % path)
+        if not path.startswith("refs/heads/"):
+            paths.append("refs/heads/%s" % path)
         refs = Store.of(self).find(
             GitRef,
             GitRef.repository_id == self.id,
@@ -864,8 +864,7 @@ class GitRepository(StormBase, WebhookTargetMixin, AccessTokenTargetMixin,
             raise ValueError('ref info object does not contain "sha1" key')
         if "type" not in obj:
             raise ValueError('ref info object does not contain "type" key')
-        if (not isinstance(obj["sha1"], six.string_types) or
-                len(obj["sha1"]) != 40):
+        if not isinstance(obj["sha1"], str) or len(obj["sha1"]) != 40:
             raise ValueError('ref info sha1 is not a 40-character string')
         if obj["type"] not in object_type_map:
             raise ValueError('ref info type is not a recognised object type')
@@ -1971,7 +1970,7 @@ class DeletionCallable(DeletionOperation):
     """Deletion operation that invokes a callable."""
 
     def __init__(self, affected_object, rationale, func, *args, **kwargs):
-        super(DeletionCallable, self).__init__(affected_object, rationale)
+        super().__init__(affected_object, rationale)
         self.func = func
         self.args = args
         self.kwargs = kwargs
@@ -2231,7 +2230,7 @@ class GitRepositoryMacaroonIssuer(MacaroonIssuerBase):
     _timestamp_format = "%Y-%m-%dT%H:%M:%S.%f"
 
     def __init__(self):
-        super(GitRepositoryMacaroonIssuer, self).__init__()
+        super().__init__()
         self.checkers = {
             "lp.principal.openid-identifier": self.verifyOpenIDIdentifier,
             "lp.expires": self.verifyExpires,
@@ -2260,8 +2259,7 @@ class GitRepositoryMacaroonIssuer(MacaroonIssuerBase):
 
     def issueMacaroon(self, context, user=None, **kwargs):
         """See `IMacaroonIssuer`."""
-        macaroon = super(GitRepositoryMacaroonIssuer, self).issueMacaroon(
-            context, user=user, **kwargs)
+        macaroon = super().issueMacaroon(context, user=user, **kwargs)
         naked_account = removeSecurityProxy(user).account
         macaroon.add_first_party_caveat(
             "lp.principal.openid-identifier " +
diff --git a/lib/lp/code/model/gitrule.py b/lib/lp/code/model/gitrule.py
index 5d416b7..b16d327 100644
--- a/lib/lp/code/model/gitrule.py
+++ b/lib/lp/code/model/gitrule.py
@@ -111,7 +111,7 @@ class GitRule(StormBase):
 
     def __init__(self, repository, position, ref_pattern, creator,
                  date_created):
-        super(GitRule, self).__init__()
+        super().__init__()
         self.repository = repository
         self.position = position
         self.ref_pattern = ref_pattern
diff --git a/lib/lp/code/model/gitsubscription.py b/lib/lp/code/model/gitsubscription.py
index 8ad435a..2c61db4 100644
--- a/lib/lp/code/model/gitsubscription.py
+++ b/lib/lp/code/model/gitsubscription.py
@@ -53,7 +53,7 @@ class GitSubscription(StormBase):
 
     def __init__(self, person, repository, notification_level, max_diff_lines,
                  review_level, subscribed_by):
-        super(GitSubscription, self).__init__()
+        super().__init__()
         self.person = person
         self.repository = repository
         self.notification_level = notification_level
diff --git a/lib/lp/code/model/recipebuilder.py b/lib/lp/code/model/recipebuilder.py
index 46ef5b8..abd82e8 100644
--- a/lib/lp/code/model/recipebuilder.py
+++ b/lib/lp/code/model/recipebuilder.py
@@ -63,8 +63,7 @@ class RecipeBuildBehaviour(BuildFarmJobBehaviourBase):
                  self.build.distroseries.displayname))
 
         # Build extra arguments.
-        args = yield super(RecipeBuildBehaviour, self).extraBuildArgs(
-            logger=logger)
+        args = yield super().extraBuildArgs(logger=logger)
         args['suite'] = self.build.distroseries.getSuite(self.build.pocket)
         requester = self.build.requester
         if requester.preferredemail is None:
diff --git a/lib/lp/code/model/revision.py b/lib/lp/code/model/revision.py
index 680f3a2..2f04cd3 100644
--- a/lib/lp/code/model/revision.py
+++ b/lib/lp/code/model/revision.py
@@ -286,7 +286,7 @@ class RevisionSet:
                            parent_id=parent_id)
 
         # Create revision properties.
-        for name, value in six.iteritems(properties):
+        for name, value in properties.items():
             RevisionProperty(revision=revision, name=name, value=value)
 
         return revision
@@ -377,7 +377,7 @@ class RevisionSet:
         for bzr_revision in revisions:
             db_id = revision_db_id[six.ensure_text(bzr_revision.revision_id)]
             # Property data: revision DB id, name, value.
-            for name, value in six.iteritems(bzr_revision.properties):
+            for name, value in bzr_revision.properties.items():
                 # pristine-tar properties can be huge, and storing them
                 # in the database provides no value. Exclude them.
                 if name.startswith('deb-pristine-delta'):
diff --git a/lib/lp/code/model/sourcepackagerecipebuild.py b/lib/lp/code/model/sourcepackagerecipebuild.py
index f10ed3c..7be41ee 100644
--- a/lib/lp/code/model/sourcepackagerecipebuild.py
+++ b/lib/lp/code/model/sourcepackagerecipebuild.py
@@ -191,7 +191,7 @@ class SourcePackageRecipeBuild(SpecificBuildFarmJobSourceMixin,
                  archive, pocket, date_created):
         """Construct a SourcePackageRecipeBuild."""
         processor = distroseries.nominatedarchindep.processor
-        super(SourcePackageRecipeBuild, self).__init__()
+        super().__init__()
         self.build_farm_job = build_farm_job
         self.distroseries = distroseries
         self.recipe = recipe
diff --git a/lib/lp/code/model/sourcepackagerecipedata.py b/lib/lp/code/model/sourcepackagerecipedata.py
index f5d849b..0185f42 100644
--- a/lib/lp/code/model/sourcepackagerecipedata.py
+++ b/lib/lp/code/model/sourcepackagerecipedata.py
@@ -105,7 +105,7 @@ class _SourcePackageRecipeDataInstruction(Storm):
     def __init__(self, name, type, comment, line_number, branch_or_repository,
                  revspec, directory, recipe_data, parent_instruction,
                  source_directory):
-        super(_SourcePackageRecipeDataInstruction, self).__init__()
+        super().__init__()
         self.name = six.ensure_text(name)
         self.type = type
         self.comment = comment
@@ -431,13 +431,13 @@ class SourcePackageRecipeData(Storm):
         else:
             self.deb_version_template = six.ensure_text(
                 builder_recipe.deb_version)
-        self.recipe_format = six.text_type(builder_recipe.format)
+        self.recipe_format = str(builder_recipe.format)
 
     def __init__(self, recipe, recipe_branch_type, sourcepackage_recipe=None,
                  sourcepackage_recipe_build=None):
         """Initialize from the bzr-builder recipe and link it to a db recipe.
         """
-        super(SourcePackageRecipeData, self).__init__()
+        super().__init__()
         self.setRecipe(recipe, recipe_branch_type)
         self.sourcepackage_recipe = sourcepackage_recipe
         self.sourcepackage_recipe_build = sourcepackage_recipe_build
diff --git a/lib/lp/code/model/tests/test_branch.py b/lib/lp/code/model/tests/test_branch.py
index 16858d2..4419b12 100644
--- a/lib/lp/code/model/tests/test_branch.py
+++ b/lib/lp/code/model/tests/test_branch.py
@@ -188,7 +188,7 @@ class TestCodeImport(TestCase):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestCodeImport, self).setUp()
+        super().setUp()
         login('test@xxxxxxxxxxxxx')
         self.factory = LaunchpadObjectFactory()
 
@@ -1468,7 +1468,7 @@ class TestBranchDeletionConsequences(TestCase):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestBranchDeletionConsequences, self).setUp()
+        super().setUp()
         login('test@xxxxxxxxxxxxx')
         self.factory = LaunchpadObjectFactory()
         # Has to be a product branch because of merge proposals.
@@ -1823,7 +1823,7 @@ class BranchAddLandingTarget(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(BranchAddLandingTarget, self).setUp('admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
         self.product = self.factory.makeProduct()
 
         self.user = self.factory.makePerson()
@@ -1837,7 +1837,7 @@ class BranchAddLandingTarget(TestCaseWithFactory):
 
     def tearDown(self):
         logout()
-        super(BranchAddLandingTarget, self).tearDown()
+        super().tearDown()
 
     def assertOnePendingReview(self, proposal, reviewer, review_type=None):
         # There should be one pending vote for the reviewer with the specified
@@ -3099,7 +3099,7 @@ class TestGetMergeProposals(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGetMergeProposals, self).setUp()
+        super().setUp()
         self.branch_set = BranchSet()
 
     def test_getMergeProposals_with_no_merged_revno(self):
@@ -3549,7 +3549,7 @@ class TestWebservice(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestWebservice, self).setUp()
+        super().setUp()
         self.branch_db = self.factory.makeBranch()
         self.branch_url = api_url(self.branch_db)
         self.webservice = webservice_for_person(
diff --git a/lib/lp/code/model/tests/test_branchcollection.py b/lib/lp/code/model/tests/test_branchcollection.py
index e66b16b..062a5ab 100644
--- a/lib/lp/code/model/tests/test_branchcollection.py
+++ b/lib/lp/code/model/tests/test_branchcollection.py
@@ -106,7 +106,7 @@ class TestGenericBranchCollection(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGenericBranchCollection, self).setUp()
+        super().setUp()
         remove_all_sample_data_branches()
         self.store = IStore(Branch)
 
diff --git a/lib/lp/code/model/tests/test_branchhosting.py b/lib/lp/code/model/tests/test_branchhosting.py
index 1e1f874..0190806 100644
--- a/lib/lp/code/model/tests/test_branchhosting.py
+++ b/lib/lp/code/model/tests/test_branchhosting.py
@@ -12,7 +12,6 @@ import re
 
 from lazr.restful.utils import get_current_browser_request
 import responses
-import six
 from testtools.matchers import MatchesStructure
 from zope.component import getUtility
 from zope.interface import implementer
@@ -47,7 +46,7 @@ class TestBranchHostingClient(TestCase):
     layer = ZopelessDatabaseLayer
 
     def setUp(self):
-        super(TestBranchHostingClient, self).setUp()
+        super().setUp()
         self.client = getUtility(IBranchHostingClient)
         self.endpoint = removeSecurityProxy(self.client).endpoint
         self.requests = []
@@ -155,14 +154,14 @@ class TestBranchHostingClient(TestCase):
             "+branch-id/123/+json/files/%2Brev%20id%3F/%2Bfile/%20name%3F")
 
     def test_getBlob(self):
-        blob = b"".join(six.int2byte(i) for i in range(256))
+        blob = b"".join(bytes((i,)) for i in range(256))
         with self.mockRequests("GET", body=blob):
             response = self.client.getBlob(123, "file-id")
         self.assertEqual(blob, response)
         self.assertRequest("+branch-id/123/download/head%3A/file-id")
 
     def test_getBlob_revision(self):
-        blob = b"".join(six.int2byte(i) for i in range(256))
+        blob = b"".join(bytes((i,)) for i in range(256))
         with self.mockRequests("GET", body=blob):
             response = self.client.getBlob(123, "file-id", rev="a")
         self.assertEqual(blob, response)
@@ -195,7 +194,7 @@ class TestBranchHostingClient(TestCase):
                 self.client.getBlob, 123, "file-id")
 
     def test_getBlob_url_quoting(self):
-        blob = b"".join(six.int2byte(i) for i in range(256))
+        blob = b"".join(bytes((i,)) for i in range(256))
         with self.mockRequests("GET", body=blob):
             self.client.getBlob(123, "+file/ id?", rev="+rev id?")
         self.assertRequest(
@@ -203,12 +202,12 @@ class TestBranchHostingClient(TestCase):
 
     def test_works_in_job(self):
         # `BranchHostingClient` is usable from a running job.
-        blob = b"".join(six.int2byte(i) for i in range(256))
+        blob = b"".join(bytes((i,)) for i in range(256))
 
         @implementer(IRunnableJob)
         class GetBlobJob(BaseRunnableJob):
             def __init__(self, testcase):
-                super(GetBlobJob, self).__init__()
+                super().__init__()
                 self.job = Job()
                 self.testcase = testcase
 
diff --git a/lib/lp/code/model/tests/test_branchjob.py b/lib/lp/code/model/tests/test_branchjob.py
index d3b7592..718df70 100644
--- a/lib/lp/code/model/tests/test_branchjob.py
+++ b/lib/lp/code/model/tests/test_branchjob.py
@@ -917,7 +917,7 @@ class TestRosettaUploadJob(TestCaseWithFactory):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestRosettaUploadJob, self).setUp()
+        super().setUp()
         self.series = None
 
     def _makeBranchWithTreeAndFile(self, file_name, file_content=None):
diff --git a/lib/lp/code/model/tests/test_branchlistingqueryoptimiser.py b/lib/lp/code/model/tests/test_branchlistingqueryoptimiser.py
index 386bb4b..319476f 100644
--- a/lib/lp/code/model/tests/test_branchlistingqueryoptimiser.py
+++ b/lib/lp/code/model/tests/test_branchlistingqueryoptimiser.py
@@ -37,8 +37,7 @@ class TestGetProductSeriesForBranches(TestCaseWithFactory):
     def setUp(self):
         # Log in as an admin as we are setting series branches, which is a
         # protected activity.
-        super(TestGetProductSeriesForBranches, self).setUp(
-            'admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
         self.product = self.factory.makeProduct()
         self.branches = [
             self.factory.makeProductBranch(product=self.product)
@@ -114,8 +113,7 @@ class TestGetOfficialSourcePackageLinksForBranches(TestCaseWithFactory):
     def setUp(self):
         # Log in an admin as we are setting official branches, which is a
         # protected activity.
-        super(TestGetOfficialSourcePackageLinksForBranches, self).setUp(
-            'admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
 
     def test_with_branches(self):
         # Test the selection of the links.
diff --git a/lib/lp/code/model/tests/test_branchmergeproposal.py b/lib/lp/code/model/tests/test_branchmergeproposal.py
index ed4fdd4..fd51edf 100644
--- a/lib/lp/code/model/tests/test_branchmergeproposal.py
+++ b/lib/lp/code/model/tests/test_branchmergeproposal.py
@@ -1027,7 +1027,7 @@ class TestMergeProposalWebhooks(WithVCSScenarios, TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestMergeProposalWebhooks, self).setUp()
+        super().setUp()
         self.useFixture(FeatureFixture(
             {BRANCH_MERGE_PROPOSAL_WEBHOOKS_FEATURE_FLAG: "on"}))
 
@@ -1509,7 +1509,7 @@ class TestBranchMergeProposalBugs(WithVCSScenarios, TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBranchMergeProposalBugs, self).setUp()
+        super().setUp()
         self.user = self.factory.makePerson()
         login_person(self.user)
         if self.git:
@@ -1690,16 +1690,15 @@ class TestBranchMergeProposalBugs(WithVCSScenarios, TestCaseWithFactory):
         bmp.updateRelatedBugsFromSource()
         self.assertEqual([bug], bmp.bugs)
         matches_expected_xref = MatchesDict(
-            {("bug", six.text_type(bug.id)):
-                ContainsDict({"metadata": Is(None)})})
+            {("bug", str(bug.id)): ContainsDict({"metadata": Is(None)})})
         self.assertThat(
             getUtility(IXRefSet).findFrom(
-                ("merge_proposal", six.text_type(bmp.id)), types=["bug"]),
+                ("merge_proposal", str(bmp.id)), types=["bug"]),
             matches_expected_xref)
         self._setUpLog([bug])
         self.assertThat(
             getUtility(IXRefSet).findFrom(
-                ("merge_proposal", six.text_type(bmp.id)), types=["bug"]),
+                ("merge_proposal", str(bmp.id)), types=["bug"]),
             matches_expected_xref)
 
     def test_updateRelatedBugsFromSource_honours_limit(self):
@@ -2252,7 +2251,7 @@ class TestScheduleDiffUpdates(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestScheduleDiffUpdates, self).setUp()
+        super().setUp()
         self.job_source = removeSecurityProxy(
             getUtility(IBranchMergeProposalJobSource))
 
@@ -2511,7 +2510,7 @@ class TestBranchMergeProposalInlineComments(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestBranchMergeProposalInlineComments, self).setUp()
+        super().setUp()
         # Create a testing IPerson, IPreviewDiff and IBranchMergeProposal
         # for tests. Log in as the testing IPerson.
         self.person = self.factory.makePerson()
diff --git a/lib/lp/code/model/tests/test_branchmergeproposaljobs.py b/lib/lp/code/model/tests/test_branchmergeproposaljobs.py
index 53f293c..44f04fc 100644
--- a/lib/lp/code/model/tests/test_branchmergeproposaljobs.py
+++ b/lib/lp/code/model/tests/test_branchmergeproposaljobs.py
@@ -197,8 +197,7 @@ class TestMergeProposalNeedsReviewEmailJobBzr(
 
     def test_run_sends_email(self):
         self.useBzrBranches(direct_database=True)
-        parent = super(TestMergeProposalNeedsReviewEmailJobBzr, self)
-        parent.test_run_sends_email()
+        super().test_run_sends_email()
 
     def test_MergeProposalCreateJob_with_sourcepackage_branch(self):
         """Jobs for merge proposals with sourcepackage branches work."""
diff --git a/lib/lp/code/model/tests/test_branchnamespace.py b/lib/lp/code/model/tests/test_branchnamespace.py
index 1c10d07..d0dad62 100644
--- a/lib/lp/code/model/tests/test_branchnamespace.py
+++ b/lib/lp/code/model/tests/test_branchnamespace.py
@@ -3,7 +3,6 @@
 
 """Tests for `IBranchNamespace` implementations."""
 
-import six
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
@@ -1106,7 +1105,7 @@ class BaseValidateNewBranchMixin:
     def test_permitted_first_character(self):
         # The first character of a branch name must be a letter or a number.
         namespace = self._getNamespace(self.factory.makePerson())
-        for c in [six.unichr(i) for i in range(128)]:
+        for c in [chr(i) for i in range(128)]:
             if c.isalnum():
                 namespace.validateBranchName(c)
             else:
@@ -1118,7 +1117,7 @@ class BaseValidateNewBranchMixin:
         # After the first character, letters, numbers and certain punctuation
         # is permitted.
         namespace = self._getNamespace(self.factory.makePerson())
-        for c in [six.unichr(i) for i in range(128)]:
+        for c in [chr(i) for i in range(128)]:
             if c.isalnum() or c in '+-_@.':
                 namespace.validateBranchName('a' + c)
             else:
diff --git a/lib/lp/code/model/tests/test_codeimport.py b/lib/lp/code/model/tests/test_codeimport.py
index 3af5208..4f9a355 100644
--- a/lib/lp/code/model/tests/test_codeimport.py
+++ b/lib/lp/code/model/tests/test_codeimport.py
@@ -85,7 +85,7 @@ class TestCodeImportBase(WithScenarios, TestCaseWithFactory):
         ]
 
     def setUp(self, *args, **kwargs):
-        super(TestCodeImportBase, self).setUp(*args, **kwargs)
+        super().setUp(*args, **kwargs)
         if self.needs_git_hosting_fixture:
             self.hosting_fixture = self.useFixture(GitHostingFixture())
 
@@ -372,8 +372,7 @@ class TestCodeImportStatusUpdate(TestCodeImportBase):
 
     def setUp(self):
         # Log in a VCS Imports member.
-        super(TestCodeImportStatusUpdate, self).setUp(
-            'david.allouche@xxxxxxxxxxxxx')
+        super().setUp('david.allouche@xxxxxxxxxxxxx')
         self.import_operator = getUtility(IPersonSet).getByEmail(
             'david.allouche@xxxxxxxxxxxxx')
         # Remove existing jobs.
@@ -505,12 +504,12 @@ class TestCodeImportResultsAttribute(TestCodeImportBase):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportResultsAttribute, self).setUp()
+        super().setUp()
         self.code_import = self.factory.makeCodeImport(
             target_rcs_type=self.target_rcs_type)
 
     def tearDown(self):
-        super(TestCodeImportResultsAttribute, self).tearDown()
+        super().tearDown()
         logout()
 
     def test_no_results(self):
@@ -571,7 +570,7 @@ class TestConsecutiveFailureCount(TestCodeImportBase):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestConsecutiveFailureCount, self).setUp()
+        super().setUp()
         login('no-priv@xxxxxxxxxxxxx')
         self.machine = self.factory.makeCodeImportMachine()
         self.machine.setOnline()
@@ -713,7 +712,7 @@ class TestTryFailingImportAgain(TestCodeImportBase):
 
     def setUp(self):
         # Log in a VCS Imports member.
-        super(TestTryFailingImportAgain, self).setUp()
+        super().setUp()
         login_person(getUtility(ILaunchpadCelebrities).vcs_imports.teamowner)
 
     def test_mustBeFailing(self):
@@ -772,7 +771,7 @@ class TestRequestImport(TestCodeImportBase):
 
     def setUp(self):
         # We have to be logged in to request imports
-        super(TestRequestImport, self).setUp(user='no-priv@xxxxxxxxxxxxx')
+        super().setUp(user='no-priv@xxxxxxxxxxxxx')
 
     def test_requestsJob(self):
         code_import = self.factory.makeCodeImport(
diff --git a/lib/lp/code/model/tests/test_codeimportjob.py b/lib/lp/code/model/tests/test_codeimportjob.py
index d2785a6..72076a2 100644
--- a/lib/lp/code/model/tests/test_codeimportjob.py
+++ b/lib/lp/code/model/tests/test_codeimportjob.py
@@ -97,7 +97,7 @@ class TestCodeImportJob(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJob, self).setUp()
+        super().setUp()
         login_for_code_imports()
 
     def assertArgumentsMatch(self, code_import, matcher, start_job=False):
@@ -211,7 +211,7 @@ class TestCodeImportJobSet(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobSet, self).setUp()
+        super().setUp()
         login_for_code_imports()
 
     def test_getByIdExisting(self):
@@ -256,7 +256,7 @@ class TestCodeImportJobSetGetJobForMachine(TestCaseWithFactory):
     def setUp(self):
         # Login so we can access the code import system, delete all jobs in
         # the sample data and set up some objects.
-        super(TestCodeImportJobSetGetJobForMachine, self).setUp()
+        super().setUp()
         login_for_code_imports()
         for job in IStore(CodeImportJob).find(CodeImportJob):
             job.destroySelf()
@@ -370,7 +370,7 @@ class ReclaimableJobTests(TestCaseWithFactory):
     LIMIT = config.codeimportworker.maximum_heartbeat_interval
 
     def setUp(self):
-        super(ReclaimableJobTests, self).setUp()
+        super().setUp()
         login_for_code_imports()
         for job in IStore(CodeImportJob).find(CodeImportJob):
             job.destroySelf()
@@ -461,7 +461,7 @@ class AssertFailureMixin:
             self.fail("AssertionError was not raised")
 
 
-class NewEvents(object):
+class NewEvents:
     """Help in testing the creation of CodeImportEvent objects.
 
     To test that an operation creates CodeImportEvent objects, create an
@@ -527,7 +527,7 @@ class TestCodeImportJobWorkflowNewJob(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowNewJob, self).setUp()
+        super().setUp()
         login_for_code_imports()
 
     def test_wrongReviewStatus(self):
@@ -631,7 +631,7 @@ class TestCodeImportJobWorkflowDeletePendingJob(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowDeletePendingJob, self).setUp()
+        super().setUp()
         self.import_admin = login_for_code_imports()
 
     def test_wrongReviewStatus(self):
@@ -687,7 +687,7 @@ class TestCodeImportJobWorkflowRequestJob(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowRequestJob, self).setUp()
+        super().setUp()
         login_for_code_imports()
 
     def test_wrongJobState(self):
@@ -779,7 +779,7 @@ class TestCodeImportJobWorkflowStartJob(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowStartJob, self).setUp()
+        super().setUp()
         login_for_code_imports()
 
     def test_wrongJobState(self):
@@ -832,7 +832,7 @@ class TestCodeImportJobWorkflowUpdateHeartbeat(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowUpdateHeartbeat, self).setUp()
+        super().setUp()
         login_for_code_imports()
 
     def test_wrongJobState(self):
@@ -867,7 +867,7 @@ class TestCodeImportJobWorkflowFinishJob(TestCaseWithFactory,
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowFinishJob, self).setUp()
+        super().setUp()
         self.vcs_imports = login_for_code_imports()
         self.machine = self.factory.makeCodeImportMachine(set_online=True)
 
@@ -1165,7 +1165,7 @@ class TestCodeImportJobWorkflowReclaimJob(TestCaseWithFactory,
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobWorkflowReclaimJob, self).setUp()
+        super().setUp()
         login_for_code_imports()
         self.machine = self.factory.makeCodeImportMachine(set_online=True)
 
@@ -1300,7 +1300,7 @@ class TestCodeImportJobMacaroonIssuer(MacaroonTestMixin, TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportJobMacaroonIssuer, self).setUp()
+        super().setUp()
         login_for_code_imports()
         self.pushConfig(
             "launchpad", internal_macaroon_secret_key="some-secret")
diff --git a/lib/lp/code/model/tests/test_codeimportmachine.py b/lib/lp/code/model/tests/test_codeimportmachine.py
index 1070610..70fcea3 100644
--- a/lib/lp/code/model/tests/test_codeimportmachine.py
+++ b/lib/lp/code/model/tests/test_codeimportmachine.py
@@ -23,8 +23,7 @@ class TestCodeImportMachineShouldLookForJob(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestCodeImportMachineShouldLookForJob, self).setUp(
-            'admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
         self.machine = self.factory.makeCodeImportMachine(set_online=True)
 
     def createJobRunningOnMachine(self, machine):
diff --git a/lib/lp/code/model/tests/test_codereviewkarma.py b/lib/lp/code/model/tests/test_codereviewkarma.py
index 5b3027b..846d05d 100644
--- a/lib/lp/code/model/tests/test_codereviewkarma.py
+++ b/lib/lp/code/model/tests/test_codereviewkarma.py
@@ -27,7 +27,7 @@ class TestCodeReviewKarma(TestCaseWithFactory):
     def setUp(self):
         # Use an admin to get launchpad.Edit on all the branches to easily
         # approve and reject the proposals.
-        super(TestCodeReviewKarma, self).setUp('admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
         self.useFixture(ZopeEventHandlerFixture(
             self._on_karma_assigned, (IPerson, IKarmaAssignedEvent)))
         self.karma_events = []
diff --git a/lib/lp/code/model/tests/test_gitcollection.py b/lib/lp/code/model/tests/test_gitcollection.py
index b3250f7..f9fdbe8 100644
--- a/lib/lp/code/model/tests/test_gitcollection.py
+++ b/lib/lp/code/model/tests/test_gitcollection.py
@@ -120,7 +120,7 @@ class TestGenericGitCollection(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGenericGitCollection, self).setUp()
+        super().setUp()
         self.store = IStore(GitRepository)
 
     def test_provides_gitcollection(self):
diff --git a/lib/lp/code/model/tests/test_githosting.py b/lib/lp/code/model/tests/test_githosting.py
index 3ca4fdc..aa3c671 100644
--- a/lib/lp/code/model/tests/test_githosting.py
+++ b/lib/lp/code/model/tests/test_githosting.py
@@ -14,7 +14,6 @@ import re
 
 from lazr.restful.utils import get_current_browser_request
 import responses
-import six
 from six.moves.urllib.parse import (
     parse_qsl,
     urlsplit,
@@ -69,7 +68,7 @@ class MatchesURL(AfterPreprocessing):
             lambda qs: sorted(parse_qsl(qs)),
             MatchesListwise(
                 [Equals(pair) for pair in sorted(parse_qsl(split_url.query))]))
-        super(MatchesURL, self).__init__(
+        super().__init__(
             urlsplit, MatchesStructure(
                 scheme=Equals(split_url.scheme),
                 netloc=Equals(split_url.netloc),
@@ -83,7 +82,7 @@ class TestGitHostingClient(TestCase):
     layer = ZopelessDatabaseLayer
 
     def setUp(self):
-        super(TestGitHostingClient, self).setUp()
+        super().setUp()
         self.client = getUtility(IGitHostingClient)
         self.endpoint = removeSecurityProxy(self.client).endpoint
         self.requests = []
@@ -331,7 +330,7 @@ class TestGitHostingClient(TestCase):
                 self.client.delete, "123")
 
     def test_getBlob(self):
-        blob = b''.join(six.int2byte(i) for i in range(256))
+        blob = b''.join(bytes((i,)) for i in range(256))
         payload = {
             "data": base64.b64encode(blob).decode("UTF-8"),
             "size": len(blob),
@@ -343,7 +342,7 @@ class TestGitHostingClient(TestCase):
             "repo/123/blob/dir/path/file/name", method="GET")
 
     def test_getBlob_revision(self):
-        blob = b''.join(six.int2byte(i) for i in range(256))
+        blob = b''.join(bytes((i,)) for i in range(256))
         payload = {
             "data": base64.b64encode(blob).decode("UTF-8"),
             "size": len(blob),
@@ -378,7 +377,7 @@ class TestGitHostingClient(TestCase):
                 self.client.getBlob, "123", "dir/path/file/name")
 
     def test_getBlob_url_quoting(self):
-        blob = b''.join(six.int2byte(i) for i in range(256))
+        blob = b''.join(bytes((i,)) for i in range(256))
         payload = {
             "data": base64.b64encode(blob).decode("UTF-8"),
             "size": len(blob),
@@ -411,7 +410,7 @@ class TestGitHostingClient(TestCase):
                 self.client.getBlob, "123", "dir/path/file/name")
 
     def test_getBlob_wrong_size(self):
-        blob = b''.join(six.int2byte(i) for i in range(256))
+        blob = b''.join(bytes((i,)) for i in range(256))
         payload = {"data": base64.b64encode(blob).decode("UTF-8"), "size": 0}
         with self.mockRequests("GET", json=payload):
             self.assertRaisesWithContent(
@@ -465,7 +464,7 @@ class TestGitHostingClient(TestCase):
         @implementer(IRunnableJob)
         class GetRefsJob(BaseRunnableJob):
             def __init__(self, testcase):
-                super(GetRefsJob, self).__init__()
+                super().__init__()
                 self.job = Job()
                 self.testcase = testcase
 
diff --git a/lib/lp/code/model/tests/test_gitlookup.py b/lib/lp/code/model/tests/test_gitlookup.py
index 0f8b8fe..8914d4c 100644
--- a/lib/lp/code/model/tests/test_gitlookup.py
+++ b/lib/lp/code/model/tests/test_gitlookup.py
@@ -38,7 +38,7 @@ class TestGetByHostingPath(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGetByHostingPath, self).setUp()
+        super().setUp()
         self.lookup = getUtility(IGitLookup)
 
     def test_exists(self):
@@ -57,7 +57,7 @@ class TestGetByUniqueName(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGetByUniqueName, self).setUp()
+        super().setUp()
         self.lookup = getUtility(IGitLookup)
 
     def test_not_found(self):
@@ -121,7 +121,7 @@ class TestGetByPath(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGetByPath, self).setUp()
+        super().setUp()
         self.lookup = getUtility(IGitLookup)
 
     def test_project(self):
@@ -213,7 +213,7 @@ class TestGetByUrl(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGetByUrl, self).setUp()
+        super().setUp()
         self.lookup = getUtility(IGitLookup)
 
     def makeProjectRepository(self):
@@ -309,7 +309,7 @@ class TestGitTraverser(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitTraverser, self).setUp()
+        super().setUp()
         self.traverser = getUtility(IGitTraverser)
 
     def assertTraverses(self, path, owner, target, repository=None):
diff --git a/lib/lp/code/model/tests/test_gitnamespace.py b/lib/lp/code/model/tests/test_gitnamespace.py
index 3c4ac13..eb11aa9 100644
--- a/lib/lp/code/model/tests/test_gitnamespace.py
+++ b/lib/lp/code/model/tests/test_gitnamespace.py
@@ -5,7 +5,6 @@
 
 from unittest import mock
 
-import six
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
@@ -954,8 +953,7 @@ class TestProjectGitNamespaceCanCreateBranches(
 
     def setUp(self):
         # Setting visibility policies is an admin-only task.
-        super(TestProjectGitNamespaceCanCreateBranches, self).setUp(
-            "admin@xxxxxxxxxxxxx")
+        super().setUp("admin@xxxxxxxxxxxxx")
 
     def test_any_person(self):
         # If there is no privacy set up, any person can create a personal
@@ -1117,7 +1115,7 @@ class BaseValidateNewRepositoryMixin:
         # The first character of a repository name must be a letter or a
         # number.
         namespace = self._getNamespace(self.factory.makePerson())
-        for c in [six.unichr(i) for i in range(128)]:
+        for c in [chr(i) for i in range(128)]:
             if c.isalnum():
                 namespace.validateRepositoryName(c)
             else:
@@ -1129,7 +1127,7 @@ class BaseValidateNewRepositoryMixin:
         # After the first character, letters, numbers and certain
         # punctuation is permitted.
         namespace = self._getNamespace(self.factory.makePerson())
-        for c in [six.unichr(i) for i in range(128)]:
+        for c in [chr(i) for i in range(128)]:
             if c.isalnum() or c in "+-_@.":
                 namespace.validateRepositoryName("a" + c)
             else:
diff --git a/lib/lp/code/model/tests/test_gitref.py b/lib/lp/code/model/tests/test_gitref.py
index b97e345..f18287a 100644
--- a/lib/lp/code/model/tests/test_gitref.py
+++ b/lib/lp/code/model/tests/test_gitref.py
@@ -159,7 +159,7 @@ class TestGitRefGetCommits(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestGitRefGetCommits, self).setUp()
+        super().setUp()
         [self.ref] = self.factory.makeGitRefs()
         self.authors = [self.factory.makePerson() for _ in range(2)]
         with admin_logged_in():
@@ -492,7 +492,7 @@ class TestGitRefCreateMergeProposal(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitRefCreateMergeProposal, self).setUp()
+        super().setUp()
         with admin_logged_in():
             self.project = self.factory.makeProduct()
             self.user = self.factory.makePerson()
diff --git a/lib/lp/code/model/tests/test_gitrepository.py b/lib/lp/code/model/tests/test_gitrepository.py
index 6a759be..6155836 100644
--- a/lib/lp/code/model/tests/test_gitrepository.py
+++ b/lib/lp/code/model/tests/test_gitrepository.py
@@ -601,7 +601,7 @@ class TestGitIdentityMixin(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitIdentityMixin, self).setUp()
+        super().setUp()
         self.repository_set = getUtility(IGitRepositorySet)
 
     def assertGitIdentity(self, repository, identity_path):
@@ -792,7 +792,7 @@ class TestGitRepositoryDeletion(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestGitRepositoryDeletion, self).setUp()
+        super().setUp()
         self.user = self.factory.makePerson()
         self.project = self.factory.makeProduct(owner=self.user)
         self.repository = self.factory.makeGitRepository(
@@ -1001,8 +1001,7 @@ class TestGitRepositoryDeletionConsequences(TestCaseWithFactory):
     layer = ZopelessDatabaseLayer
 
     def setUp(self):
-        super(TestGitRepositoryDeletionConsequences, self).setUp(
-            user="test@xxxxxxxxxxxxx")
+        super().setUp(user="test@xxxxxxxxxxxxx")
         self.repository = self.factory.makeGitRepository()
         [self.ref] = self.factory.makeGitRefs(repository=self.repository)
         # The owner of the repository is subscribed to the repository when
@@ -1537,7 +1536,7 @@ class TestGitRepositoryPrivacy(TestCaseWithFactory):
 
     def setUp(self):
         # Use an admin user as we aren't checking edit permissions here.
-        super(TestGitRepositoryPrivacy, self).setUp("admin@xxxxxxxxxxxxx")
+        super().setUp("admin@xxxxxxxxxxxxx")
 
     def test_personal_repositories_for_private_teams_are_private(self):
         team = self.factory.makeTeam(
@@ -2865,7 +2864,7 @@ class TestGitRepositoryFork(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitRepositoryFork, self).setUp()
+        super().setUp()
         self.hosting_fixture = self.useFixture(GitHostingFixture())
 
     def test_fork(self):
@@ -3474,7 +3473,7 @@ class TestGitRepositorySet(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitRepositorySet, self).setUp()
+        super().setUp()
         self.repository_set = getUtility(IGitRepositorySet)
 
     def test_new(self):
@@ -3775,7 +3774,7 @@ class TestGitRepositorySetDefaultsMixin:
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitRepositorySetDefaultsMixin, self).setUp()
+        super().setUp()
         self.repository_set = getUtility(IGitRepositorySet)
         self.get_method = self.repository_set.getDefaultRepository
         self.set_method = (lambda target, repository, user:
@@ -3857,7 +3856,7 @@ class TestGitRepositorySetDefaultsOwnerMixin(
     TestGitRepositorySetDefaultsMixin):
 
     def setUp(self):
-        super(TestGitRepositorySetDefaultsOwnerMixin, self).setUp()
+        super().setUp()
         self.person = self.factory.makePerson()
         self.get_method = partial(
             self.repository_set.getDefaultRepositoryForOwner, self.person)
@@ -4098,7 +4097,7 @@ class TestGitRepositoryWebservice(TestCaseWithFactory):
         self.assertNewWorks(self.factory.makePerson())
 
     def test_new_repo_not_owner(self):
-        non_ascii_name = u'André Luís Lopes'
+        non_ascii_name = 'André Luís Lopes'
         other_user = self.factory.makePerson(displayname=non_ascii_name)
         owner_url = api_url(other_user)
         webservice_user = self.factory.makePerson()
@@ -4109,8 +4108,8 @@ class TestGitRepositoryWebservice(TestCaseWithFactory):
         response = webservice.named_post(
             "/+git", "new", owner=owner_url, target=owner_url, name=name)
         self.assertEqual(400, response.status)
-        self.assertIn(u'cannot create Git repositories owned by'
-                      u' André Luís Lopes', response.body.decode('utf-8'))
+        self.assertIn('cannot create Git repositories owned by'
+                      ' André Luís Lopes', response.body.decode('utf-8'))
 
     def assertGetRepositoriesWorks(self, target_db):
         if IPerson.providedBy(target_db):
@@ -4978,7 +4977,7 @@ class TestRevisionStatusReportWebservice(TestCaseWithFactory):
     layer = LaunchpadFunctionalLayer
 
     def setUp(self):
-        super(TestRevisionStatusReportWebservice, self).setUp()
+        super().setUp()
         self.repository = self.factory.makeGitRepository()
         self.requester = self.repository.owner
         title = self.factory.getUniqueUnicode('report-title')
@@ -5034,7 +5033,7 @@ class TestGitRepositoryMacaroonIssuer(MacaroonTestMixin, TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitRepositoryMacaroonIssuer, self).setUp()
+        super().setUp()
         self.pushConfig("codehosting", git_macaroon_secret_key="some-secret")
 
     def test_issueMacaroon_refuses_branch(self):
diff --git a/lib/lp/code/model/tests/test_revision.py b/lib/lp/code/model/tests/test_revision.py
index 957f2ca..bdd0f7a 100644
--- a/lib/lp/code/model/tests/test_revision.py
+++ b/lib/lp/code/model/tests/test_revision.py
@@ -204,7 +204,7 @@ class TestRevisionSet(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestRevisionSet, self).setUp()
+        super().setUp()
         self.revision_set = getUtility(IRevisionSet)
 
     def test_getRevisionById_existing(self):
diff --git a/lib/lp/code/model/tests/test_revisionauthor.py b/lib/lp/code/model/tests/test_revisionauthor.py
index 4953571..9941c7f 100644
--- a/lib/lp/code/model/tests/test_revisionauthor.py
+++ b/lib/lp/code/model/tests/test_revisionauthor.py
@@ -35,7 +35,7 @@ class TestRevisionEmailExtraction(TestCase):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestRevisionEmailExtraction, self).setUp()
+        super().setUp()
         switch_dbuser("branchscanner")
 
     def test_email_extracted_from_name(self):
@@ -134,7 +134,7 @@ class TestNewlyValidatedEmailsLinkRevisionAuthors(MakeHarryTestCase):
 
     def setUp(self):
         # Create a revision author that doesn't have a user yet.
-        super(TestNewlyValidatedEmailsLinkRevisionAuthors, self).setUp()
+        super().setUp()
         with dbuser("branchscanner"):
             self.author = RevisionSet()._createRevisionAuthor(
                 '"Harry Potter" <harry@xxxxxxxxxxxxx>')
@@ -171,35 +171,35 @@ class TestRevisionAuthor(TestCase):
     layer = LaunchpadZopelessLayer
 
     def setUp(self):
-        super(TestRevisionAuthor, self).setUp()
+        super().setUp()
         switch_dbuser("branchscanner")
 
     def testGetNameWithoutEmailReturnsNamePart(self):
         # name_without_email is equal to the 'name' part of the revision
         # author information.
-        author = RevisionAuthor(name=u'Jonathan Lange <jml@xxxxxxxxxxxxx>')
-        self.assertEqual(u'Jonathan Lange', author.name_without_email)
+        author = RevisionAuthor(name='Jonathan Lange <jml@xxxxxxxxxxxxx>')
+        self.assertEqual('Jonathan Lange', author.name_without_email)
 
     def testGetNameWithoutEmailWithNoName(self):
         # If there is no name in the revision author information,
         # name_without_email is an empty string.
-        author = RevisionAuthor(name=u'jml@xxxxxxxxx')
+        author = RevisionAuthor(name='jml@xxxxxxxxx')
         self.assertEqual('', author.name_without_email)
 
     def testGetNameWithoutEmailWithNoEmail(self):
         # If there is no email in the revision author information,
         # name_without_email is the name.
-        author = RevisionAuthor(name=u'Jonathan Lange')
+        author = RevisionAuthor(name='Jonathan Lange')
         self.assertEqual('Jonathan Lange', author.name_without_email)
 
     def testGetNameWithoutEmailWithOneWord(self):
         # If there is no email in the revision author information,
         # name_without_email is the name.
-        author = RevisionAuthor(name=u'Jonathan.Lange')
+        author = RevisionAuthor(name='Jonathan.Lange')
         self.assertEqual('Jonathan.Lange', author.name_without_email)
 
     def testGetNameWithoutEmailWithBadEmail(self):
         # If there is an invalid email in the revision author information,
         # name_without_email is an empty string.
-        author = RevisionAuthor(name=u'jml@localhost')
+        author = RevisionAuthor(name='jml@localhost')
         self.assertEqual('', author.name_without_email)
diff --git a/lib/lp/code/model/tests/test_sourcepackagerecipe.py b/lib/lp/code/model/tests/test_sourcepackagerecipe.py
index 719ab3b..4837166 100644
--- a/lib/lp/code/model/tests/test_sourcepackagerecipe.py
+++ b/lib/lp/code/model/tests/test_sourcepackagerecipe.py
@@ -859,7 +859,7 @@ class TestRecipeBranchRoundTrippingMixin:
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestRecipeBranchRoundTrippingMixin, self).setUp()
+        super().setUp()
         self.base_branch = self.makeBranch()
         self.nested_branch = self.makeBranch()
         self.merged_branch = self.makeBranch()
diff --git a/lib/lp/code/scripts/repackgitrepository.py b/lib/lp/code/scripts/repackgitrepository.py
index 9a202a4..6c880da 100644
--- a/lib/lp/code/scripts/repackgitrepository.py
+++ b/lib/lp/code/scripts/repackgitrepository.py
@@ -6,7 +6,6 @@
 from datetime import timedelta
 
 from psycopg2.extensions import TransactionRollbackError
-import six
 from storm.expr import (
     Cast,
     Or,
@@ -33,7 +32,7 @@ class RepackTunableLoop(TunableLoop):
     targets = 1000
 
     def __init__(self, log, dry_run, abort_time=None):
-        super(RepackTunableLoop, self).__init__(log, abort_time)
+        super().__init__(log, abort_time)
         self.dry_run = dry_run
         self.start_at = 0
         self.logger = log
@@ -103,7 +102,7 @@ class RepackTunableLoop(TunableLoop):
             except TransactionRollbackError as error:
                 self.logger.error(
                     'An error occurred while requesting repository repack %s'
-                    % six.text_type(error))
+                    % str(error))
                 if transaction is not None:
                     transaction.abort()
                 continue
diff --git a/lib/lp/code/scripts/tests/test_repack_git_repositories.py b/lib/lp/code/scripts/tests/test_repack_git_repositories.py
index 9314997..77d1fad 100644
--- a/lib/lp/code/scripts/tests/test_repack_git_repositories.py
+++ b/lib/lp/code/scripts/tests/test_repack_git_repositories.py
@@ -52,7 +52,7 @@ class FakeTurnipServer(threading.Thread):
     """Thread that runs a fake turnip server."""
 
     def __init__(self):
-        super(FakeTurnipServer, self).__init__()
+        super().__init__()
         self.name = 'FakeTurnipServer'
         self.app = FakeTurnipApplication()
         self.server = make_server(
@@ -74,7 +74,7 @@ class TestRequestGitRepack(TestCaseWithFactory):
     layer = ZopelessAppServerLayer
 
     def setUp(self):
-        super(TestRequestGitRepack, self).setUp()
+        super().setUp()
         self.log = logging.getLogger('repack')
 
     def runScript_no_Turnip(self):
diff --git a/lib/lp/code/scripts/tests/test_request_daily_builds.py b/lib/lp/code/scripts/tests/test_request_daily_builds.py
index d1ac03a..0d9b970 100644
--- a/lib/lp/code/scripts/tests/test_request_daily_builds.py
+++ b/lib/lp/code/scripts/tests/test_request_daily_builds.py
@@ -102,7 +102,7 @@ class FakeLoggerheadServer(threading.Thread):
     """Thread that runs a fake loggerhead server."""
 
     def __init__(self):
-        super(FakeLoggerheadServer, self).__init__()
+        super().__init__()
         self.app = FakeLoggerheadApplication()
         self.server = make_server(
             'localhost', 0, self.app, handler_class=SilentWSGIRequestHandler)
@@ -162,7 +162,7 @@ class FakeTurnipServer(threading.Thread):
     """Thread that runs a fake turnip server."""
 
     def __init__(self):
-        super(FakeTurnipServer, self).__init__()
+        super().__init__()
         self.app = FakeTurnipApplication()
         self.server = make_server(
             'localhost', 0, self.app, handler_class=SilentWSGIRequestHandler)
@@ -186,7 +186,7 @@ class TestRequestDailyBuilds(TestCaseWithFactory):
     layer = ZopelessAppServerLayer
 
     def setUp(self):
-        super(TestRequestDailyBuilds, self).setUp()
+        super().setUp()
         features = dict(SNAP_TESTING_FLAGS)
         features[CHARM_RECIPE_ALLOW_CREATE] = "on"
         self.useFixture(FeatureFixture(features))
diff --git a/lib/lp/code/tests/helpers.py b/lib/lp/code/tests/helpers.py
index a240ab4..f566b60 100644
--- a/lib/lp/code/tests/helpers.py
+++ b/lib/lp/code/tests/helpers.py
@@ -150,8 +150,7 @@ def consistent_branch_names():
 
     This generator does not finish!
     """
-    for name in ['trunk', 'testing', 'feature-x', 'feature-y', 'feature-z']:
-        yield name
+    yield from ['trunk', 'testing', 'feature-x', 'feature-y', 'feature-z']
     index = count(1)
     while True:
         yield "branch-%s" % next(index)
diff --git a/lib/lp/code/tests/test_branch.py b/lib/lp/code/tests/test_branch.py
index a9e704d..5b316f3 100644
--- a/lib/lp/code/tests/test_branch.py
+++ b/lib/lp/code/tests/test_branch.py
@@ -331,7 +331,7 @@ class TestComposePublicURL(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestComposePublicURL, self).setUp('admin@xxxxxxxxxxxxx')
+        super().setUp('admin@xxxxxxxxxxxxx')
 
     def test_composePublicURL_accepts_supported_schemes(self):
         # composePublicURL accepts all schemes that PublicCodehostingAPI
diff --git a/lib/lp/code/tests/test_branch_webservice.py b/lib/lp/code/tests/test_branch_webservice.py
index 653ea5c..0a7e495 100644
--- a/lib/lp/code/tests/test_branch_webservice.py
+++ b/lib/lp/code/tests/test_branch_webservice.py
@@ -175,7 +175,7 @@ class TestBranchDeletes(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBranchDeletes, self).setUp()
+        super().setUp()
         self.branch_owner = self.factory.makePerson(name='jimhenson')
         self.branch = self.factory.makeBranch(
             owner=self.branch_owner,
diff --git a/lib/lp/code/tests/test_bzr.py b/lib/lp/code/tests/test_bzr.py
index 7f6939c..d430ad0 100644
--- a/lib/lp/code/tests/test_bzr.py
+++ b/lib/lp/code/tests/test_bzr.py
@@ -9,7 +9,6 @@ from breezy.tests import (
     TestCaseInTempDir,
     TestCaseWithTransport,
     )
-import six
 
 from lp.code.bzr import (
     branch_revision_history,
@@ -46,7 +45,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_2a(self):
         # Test the 2a branch format.
-        branch = self.make_branch('test', six.ensure_str('2a'))
+        branch = self.make_branch('test', '2a')
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_7, formats[1])
@@ -54,7 +53,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_1_9(self):
         # Test the 1.9 branch format.
-        branch = self.make_branch('test', six.ensure_str('1.9'))
+        branch = self.make_branch('test', '1.9')
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_7, formats[1])
@@ -62,7 +61,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_packs(self):
         # Test the packs branch format.
-        branch = self.make_branch('test', six.ensure_str('pack-0.92'))
+        branch = self.make_branch('test', 'pack-0.92')
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_6, formats[1])
@@ -70,7 +69,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_knits(self):
         # Test the knits branch format.
-        branch = self.make_branch('test', six.ensure_str('knit'))
+        branch = self.make_branch('test', 'knit')
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_5, formats[1])
diff --git a/lib/lp/code/tests/test_directbranchcommit.py b/lib/lp/code/tests/test_directbranchcommit.py
index 977d855..db4d71c 100644
--- a/lib/lp/code/tests/test_directbranchcommit.py
+++ b/lib/lp/code/tests/test_directbranchcommit.py
@@ -30,7 +30,7 @@ class DirectBranchCommitTestCase:
     committer = None
 
     def setUp(self):
-        super(DirectBranchCommitTestCase, self).setUp()
+        super().setUp()
         self.useBzrBranches(direct_database=True)
 
         self.series = self.factory.makeProductSeries()
@@ -292,7 +292,7 @@ class TestGetBzrCommitterID(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGetBzrCommitterID, self).setUp()
+        super().setUp()
         self.useBzrBranches(direct_database=True)
 
     def _makeBranch(self, **kwargs):
diff --git a/lib/lp/code/tests/test_project.py b/lib/lp/code/tests/test_project.py
index d765060..7230a94 100644
--- a/lib/lp/code/tests/test_project.py
+++ b/lib/lp/code/tests/test_project.py
@@ -12,7 +12,7 @@ class TestProjectBranches(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestProjectBranches, self).setUp()
+        super().setUp()
         self.projectgroup = self.factory.makeProject()
         self.product = self.factory.makeProduct(projectgroup=self.projectgroup)
 
diff --git a/lib/lp/code/vocabularies/branch.py b/lib/lp/code/vocabularies/branch.py
index b165edc..d1b5eb9 100644
--- a/lib/lp/code/vocabularies/branch.py
+++ b/lib/lp/code/vocabularies/branch.py
@@ -70,7 +70,7 @@ class BranchRestrictedOnProductVocabulary(BranchVocabulary):
     """A vocabulary for searching branches restricted on product."""
 
     def __init__(self, context=None):
-        super(BranchRestrictedOnProductVocabulary, self).__init__(context)
+        super().__init__(context)
         if IProduct.providedBy(self.context):
             self.product = self.context
         elif IProductSeries.providedBy(self.context):
@@ -94,7 +94,7 @@ class HostedBranchRestrictedOnOwnerVocabulary(BranchVocabulary):
 
     def __init__(self, context=None):
         """Pass a Person as context, or anything else for the current user."""
-        super(HostedBranchRestrictedOnOwnerVocabulary, self).__init__(context)
+        super().__init__(context)
         if IPerson.providedBy(self.context):
             self.user = self.context
         else:
diff --git a/lib/lp/code/vocabularies/gitref.py b/lib/lp/code/vocabularies/gitref.py
index de842d1..2a2bad3 100644
--- a/lib/lp/code/vocabularies/gitref.py
+++ b/lib/lp/code/vocabularies/gitref.py
@@ -59,7 +59,7 @@ class GitRefVocabulary(StormVocabularyBase):
     step_title = "Search"
 
     def __init__(self, context):
-        super(GitRefVocabulary, self).__init__(context=context)
+        super().__init__(context=context)
         if IReference.providedBy(context):
             context = context.context
         try:
@@ -135,7 +135,7 @@ class GitRefVocabulary(StormVocabularyBase):
         # remote refs aren't database backed
         if zope_isinstance(value, GitRefRemote):
             return self.toTerm(value)
-        return super(GitRefVocabulary, self).getTerm(value)
+        return super().getTerm(value)
 
     def __len__(self):
         """See `IVocabulary`."""
diff --git a/lib/lp/code/vocabularies/gitrepository.py b/lib/lp/code/vocabularies/gitrepository.py
index 4f6f9df..92f8c3c 100644
--- a/lib/lp/code/vocabularies/gitrepository.py
+++ b/lib/lp/code/vocabularies/gitrepository.py
@@ -67,8 +67,7 @@ class GitRepositoryRestrictedOnProductVocabulary(GitRepositoryVocabulary):
     """A vocabulary for searching git repositories restricted on product."""
 
     def __init__(self, context):
-        super(GitRepositoryRestrictedOnProductVocabulary, self).__init__(
-            context)
+        super().__init__(context)
         if IProduct.providedBy(self.context):
             self.product = self.context
         else:
diff --git a/lib/lp/code/vocabularies/gitrule.py b/lib/lp/code/vocabularies/gitrule.py
index 4b6284b..f6be79b 100644
--- a/lib/lp/code/vocabularies/gitrule.py
+++ b/lib/lp/code/vocabularies/gitrule.py
@@ -102,4 +102,4 @@ class GitPermissionsVocabulary(SimpleVocabulary):
                 terms.append(SimpleTerm(
                     grant_permissions,
                     "custom", "Custom permissions: %s" % ", ".join(names)))
-        super(GitPermissionsVocabulary, self).__init__(terms)
+        super().__init__(terms)
diff --git a/lib/lp/code/vocabularies/tests/test_branch_vocabularies.py b/lib/lp/code/vocabularies/tests/test_branch_vocabularies.py
index 7773c17..23d018f 100644
--- a/lib/lp/code/vocabularies/tests/test_branch_vocabularies.py
+++ b/lib/lp/code/vocabularies/tests/test_branch_vocabularies.py
@@ -22,7 +22,7 @@ class TestBranchVocabulary(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestBranchVocabulary, self).setUp()
+        super().setUp()
         self._createBranches()
         self.vocab = BranchVocabulary(context=None)
 
@@ -40,8 +40,7 @@ class TestBranchVocabulary(TestCaseWithFactory):
     def test_fizzbuzzBranches(self):
         """Return branches that match the string 'fizzbuzz'."""
         results = self.vocab.searchForTerms('fizzbuzz')
-        expected = [
-            u'~scotty/sprocket/fizzbuzz', u'~scotty/widget/fizzbuzz']
+        expected = ['~scotty/sprocket/fizzbuzz', '~scotty/widget/fizzbuzz']
         branch_names = sorted(branch.token for branch in results)
         self.assertEqual(expected, branch_names)
 
@@ -68,7 +67,7 @@ class TestRestrictedBranchVocabularyOnProduct(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestRestrictedBranchVocabularyOnProduct, self).setUp()
+        super().setUp()
         self._createBranches()
         self.vocab = BranchRestrictedOnProductVocabulary(
             context=self._getVocabRestriction())
@@ -98,7 +97,7 @@ class TestRestrictedBranchVocabularyOnProduct(TestCaseWithFactory):
         The result set should not show ~scotty/sprocket/main.
         """
         results = self.vocab.searchForTerms('main')
-        expected = [u'~scotty/widget/main']
+        expected = ['~scotty/widget/main']
         branch_names = sorted(branch.token for branch in results)
         self.assertEqual(expected, branch_names)
 
diff --git a/lib/lp/code/vocabularies/tests/test_gitrepository_vocabularies.py b/lib/lp/code/vocabularies/tests/test_gitrepository_vocabularies.py
index 774b0a1..d64d8c0 100644
--- a/lib/lp/code/vocabularies/tests/test_gitrepository_vocabularies.py
+++ b/lib/lp/code/vocabularies/tests/test_gitrepository_vocabularies.py
@@ -20,7 +20,7 @@ class TestGitRepositoryVocabulary(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestGitRepositoryVocabulary, self).setUp()
+        super().setUp()
         self._createRepositories()
         self.vocab = GitRepositoryVocabulary(context=None)
 
@@ -29,17 +29,17 @@ class TestGitRepositoryVocabulary(TestCaseWithFactory):
         sprocket = self.factory.makeProduct(name="sprocket")
         scotty = self.factory.makePerson(name="scotty")
         self.factory.makeGitRepository(
-            owner=scotty, target=widget, name=u"fizzbuzz")
+            owner=scotty, target=widget, name="fizzbuzz")
         self.factory.makeGitRepository(
-            owner=scotty, target=widget, name=u"mountain")
+            owner=scotty, target=widget, name="mountain")
         self.factory.makeGitRepository(
-            owner=scotty, target=sprocket, name=u"fizzbuzz")
+            owner=scotty, target=sprocket, name="fizzbuzz")
 
     def test_fizzbuzzRepositories(self):
         """Return repositories that match the string 'fizzbuzz'."""
         results = self.vocab.searchForTerms("fizzbuzz")
         expected = [
-            u"~scotty/sprocket/+git/fizzbuzz", u"~scotty/widget/+git/fizzbuzz"]
+            "~scotty/sprocket/+git/fizzbuzz", "~scotty/widget/+git/fizzbuzz"]
         repository_names = sorted(repository.token for repository in results)
         self.assertEqual(expected, repository_names)
 
@@ -67,7 +67,7 @@ class TestRestrictedGitRepositoryVocabularyOnProduct(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestRestrictedGitRepositoryVocabularyOnProduct, self).setUp()
+        super().setUp()
         self._createRepositories()
         self.vocab = GitRepositoryRestrictedOnProductVocabulary(
             context=self._getVocabRestriction())
@@ -79,11 +79,11 @@ class TestRestrictedGitRepositoryVocabularyOnProduct(TestCaseWithFactory):
     def _createRepositories(self):
         test_product = self.factory.makeProduct(name='widget')
         other_product = self.factory.makeProduct(name='sprocket')
-        person = self.factory.makePerson(name=u'scotty')
+        person = self.factory.makePerson(name='scotty')
         self.factory.makeGitRepository(
-            owner=person, target=test_product, name=u'mountain')
+            owner=person, target=test_product, name='mountain')
         self.factory.makeGitRepository(
-            owner=person, target=other_product, name=u'mountain')
+            owner=person, target=other_product, name='mountain')
         self.product = test_product
         self.other_product = test_product
 
@@ -93,7 +93,7 @@ class TestRestrictedGitRepositoryVocabularyOnProduct(TestCaseWithFactory):
         The result set should not show ~scotty/sprocket/mountain.
         """
         results = self.vocab.searchForTerms('mountain')
-        expected = [u'~scotty/widget/+git/mountain']
+        expected = ['~scotty/widget/+git/mountain']
         repo_names = sorted(repo.token for repo in results)
         self.assertEqual(expected, repo_names)
 
@@ -102,7 +102,7 @@ class TestRestrictedGitRepositoryVocabularyOnProduct(TestCaseWithFactory):
         # as the result.
         term = self.vocab.getTermByToken('mountain')
         self.assertEqual(
-            u'~scotty/widget/+git/mountain', term.value.unique_name)
+            '~scotty/widget/+git/mountain', term.value.unique_name)
 
     def test_multipleQueryResult(self):
         # If there are more than one search result, a LookupError is still
diff --git a/lib/lp/code/xmlrpc/codehosting.py b/lib/lp/code/xmlrpc/codehosting.py
index c32d69f..07416b0 100644
--- a/lib/lp/code/xmlrpc/codehosting.py
+++ b/lib/lp/code/xmlrpc/codehosting.py
@@ -109,7 +109,7 @@ def run_with_login(login_id, function, *args, **kwargs):
         # Don't pass in an actual user. Instead pass in LAUNCHPAD_SERVICES
         # and expect `function` to use `removeSecurityProxy` or similar.
         return function(login_id, *args, **kwargs)
-    if isinstance(login_id, (six.binary_type, six.text_type)):
+    if isinstance(login_id, (bytes, str)):
         login_id = six.ensure_text(login_id)
         # OpenID identifiers must contain a slash, while names must not.
         if "/" in login_id:
diff --git a/lib/lp/code/xmlrpc/git.py b/lib/lp/code/xmlrpc/git.py
index 9278b1a..83383cd 100644
--- a/lib/lp/code/xmlrpc/git.py
+++ b/lib/lp/code/xmlrpc/git.py
@@ -131,7 +131,7 @@ class GitAPI(LaunchpadXMLRPCView):
     """See `IGitAPI`."""
 
     def __init__(self, *args, **kwargs):
-        super(GitAPI, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.repository_set = getUtility(IGitRepositorySet)
 
     def _verifyMacaroon(self, macaroon_raw, repository=None, user=None):
@@ -326,7 +326,7 @@ class GitAPI(LaunchpadXMLRPCView):
     def _reportError(self, path, exception, hosting_path=None):
         properties = [
             ("path", path),
-            ("error-explanation", six.text_type(exception)),
+            ("error-explanation", str(exception)),
             ]
         if hosting_path is not None:
             properties.append(("hosting_path", hosting_path))
@@ -360,9 +360,9 @@ class GitAPI(LaunchpadXMLRPCView):
                 raise faults.InvalidSourcePackageName(e.name)
             return self._createRepository(requester, path)
         except NameLookupFailed as e:
-            raise faults.NotFound(six.text_type(e))
+            raise faults.NotFound(str(e))
         except GitRepositoryCreationForbidden as e:
-            raise faults.PermissionDenied(six.text_type(e))
+            raise faults.PermissionDenied(str(e))
 
         try:
             try:
@@ -391,7 +391,7 @@ class GitAPI(LaunchpadXMLRPCView):
                 # private repository).  Log an OOPS for investigation.
                 self._reportError(path, e)
             except (GitRepositoryCreationException, Unauthorized) as e:
-                raise faults.PermissionDenied(six.text_type(e))
+                raise faults.PermissionDenied(str(e))
             except GitRepositoryCreationFault as e:
                 # The hosting service failed.  Log an OOPS for investigation.
                 self._reportError(path, e, hosting_path=e.path)
diff --git a/lib/lp/code/xmlrpc/tests/test_branch.py b/lib/lp/code/xmlrpc/tests/test_branch.py
index 41d55d7..58d2192 100644
--- a/lib/lp/code/xmlrpc/tests/test_branch.py
+++ b/lib/lp/code/xmlrpc/tests/test_branch.py
@@ -24,7 +24,7 @@ from lp.testing.layers import DatabaseFunctionalLayer
 from lp.xmlrpc import faults
 
 
-NON_ASCII_NAME = u'nam\N{LATIN SMALL LETTER E WITH ACUTE}'
+NON_ASCII_NAME = 'nam\N{LATIN SMALL LETTER E WITH ACUTE}'
 
 
 class TestExpandURL(TestCaseWithFactory):
@@ -193,7 +193,7 @@ class TestExpandURL(TestCaseWithFactory):
         # find a branch, but it still resolves rather than erroring.
         owner = self.factory.makePerson()
         product = self.factory.makeProduct()
-        nonexistent_branch = u'~%s/%s/%s' % (
+        nonexistent_branch = '~%s/%s/%s' % (
             owner.name, product.name, NON_ASCII_NAME)
         self.assertResolves(
             nonexistent_branch, urlutils.escape(nonexistent_branch))
@@ -236,7 +236,7 @@ class TestExpandURL(TestCaseWithFactory):
     def test_resolve_branch_with_no_such_owner_non_ascii(self):
         # lp:~<non-ascii-string>/product/name returns NoSuchPersonWithName
         # with the name escaped.
-        nonexistent_owner_branch = u"~%s/%s/%s" % (
+        nonexistent_owner_branch = "~%s/%s/%s" % (
             NON_ASCII_NAME, self.factory.getUniqueString(),
             self.factory.getUniqueString())
         self.assertFault(
diff --git a/lib/lp/code/xmlrpc/tests/test_codehosting.py b/lib/lp/code/xmlrpc/tests/test_codehosting.py
index e72e46b..4921642 100644
--- a/lib/lp/code/xmlrpc/tests/test_codehosting.py
+++ b/lib/lp/code/xmlrpc/tests/test_codehosting.py
@@ -85,7 +85,7 @@ class TestRunWithLogin(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
-        super(TestRunWithLogin, self).setUp()
+        super().setUp()
         self.person = self.factory.makePerson()
 
     def test_loginAsRequester(self):
@@ -114,7 +114,7 @@ class TestRunWithLogin(TestCaseWithFactory):
                 self.person.account.openid_identifiers.one().identifier)
         username = run_with_login(
             # Deliberately not Unicode, since XML-RPC gives us a byte string.
-            (u'http://testopenid.test/+id/%s' % identifier).encode("UTF-8"),
+            ('http://testopenid.test/+id/%s' % identifier).encode("UTF-8"),
             get_logged_in_username)
         login(ANONYMOUS)
         self.assertEqual(self.person.name, username)
@@ -306,7 +306,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
 
     def test_createBranch_no_preceding_slash(self):
         requester = self.factory.makePerson()
-        path = escape(u'invalid')
+        path = escape('invalid')
         fault = self.codehosting_api.createBranch(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(faults.InvalidPath(path), fault)
@@ -390,7 +390,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # Creating a branch with an invalid name fails.
         owner = self.factory.makePerson()
         product = self.factory.makeProduct()
-        invalid_name = u'invalid\N{LATIN SMALL LETTER E WITH ACUTE}'
+        invalid_name = 'invalid\N{LATIN SMALL LETTER E WITH ACUTE}'
         # LaunchpadValidationError unfortunately assumes its output is
         # always HTML, so it ends up double-escaped in XML-RPC faults.
         message = html_escape(
@@ -526,8 +526,8 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         owner = self.factory.makePerson()
         product = self.factory.makeProduct()
         branch_name = self.factory.getUniqueString('branch-name')
-        unique_name = u'~%s/%s/%s' % (owner.name, product.name, branch_name)
-        path = u'/%s/%s' % (BRANCH_ALIAS_PREFIX, unique_name)
+        unique_name = '~%s/%s/%s' % (owner.name, product.name, branch_name)
+        path = '/%s/%s' % (BRANCH_ALIAS_PREFIX, unique_name)
         branch_id = self.codehosting_api.createBranch(owner.id, escape(path))
         login(ANONYMOUS)
         branch = self.branch_lookup.get(branch_id)
@@ -539,8 +539,8 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         owner = self.factory.makePerson()
         product = self.factory.makeProduct()
         branch_name = self.factory.getUniqueString('branch-name')
-        unique_name = u'~%s/%s/%s' % (owner.name, product.name, branch_name)
-        path = escape(u'/%s/%s' % (BRANCH_ALIAS_PREFIX, unique_name))
+        unique_name = '~%s/%s/%s' % (owner.name, product.name, branch_name)
+        path = escape('/%s/%s' % (BRANCH_ALIAS_PREFIX, unique_name))
         branch_id = self.codehosting_api.createBranch(owner.id, path)
         login(ANONYMOUS)
         translation = self.codehosting_api.translatePath(owner.id, path)
@@ -555,7 +555,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # it.
         owner = self.factory.makePerson()
         product = self.factory.makeProduct(owner=owner)
-        path = u'/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name)
+        path = '/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name)
         branch_id = self.codehosting_api.createBranch(owner.id, escape(path))
         login(ANONYMOUS)
         branch = self.branch_lookup.get(branch_id)
@@ -569,7 +569,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # immediately traversable using translatePath.
         product = self.factory.makeProduct()
         owner = product.owner
-        path = escape(u'/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name))
+        path = escape('/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name))
         branch_id = self.codehosting_api.createBranch(owner.id, path)
         login(ANONYMOUS)
         translation = self.codehosting_api.translatePath(owner.id, path)
@@ -583,7 +583,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # the new branch to the alias, then can't create the branch.
         owner = self.factory.makePerson(name='eric')
         product = self.factory.makeProduct('wibble')
-        path = u'/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name)
+        path = '/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name)
         fault = self.codehosting_api.createBranch(owner.id, escape(path))
         message = "Cannot create linked branch at 'wibble'."
         self.assertEqual(faults.PermissionDenied(message), fault)
@@ -595,7 +595,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_createBranch_using_branch_alias_product_not_exist(self):
         # If the product doesn't exist, we don't (yet) create one.
         owner = self.factory.makePerson()
-        path = u'/%s/foible' % (BRANCH_ALIAS_PREFIX,)
+        path = '/%s/foible' % (BRANCH_ALIAS_PREFIX,)
         fault = self.codehosting_api.createBranch(owner.id, escape(path))
         message = "Project 'foible' does not exist."
         self.assertEqual(faults.NotFound(message), fault)
@@ -607,7 +607,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         owner = self.factory.makePerson()
         product = self.factory.makeProduct(owner=owner)
         series = self.factory.makeProductSeries(product=product)
-        path = u'/%s/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name, series.name)
+        path = '/%s/%s/%s' % (BRANCH_ALIAS_PREFIX, product.name, series.name)
         branch_id = self.codehosting_api.createBranch(owner.id, escape(path))
         login(ANONYMOUS)
         branch = self.branch_lookup.get(branch_id)
@@ -622,7 +622,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         owner = self.factory.makePerson()
         product = self.factory.makeProduct(name='wibble')
         self.factory.makeProductSeries(product=product, name='nip')
-        path = u'/%s/wibble/nip' % (BRANCH_ALIAS_PREFIX,)
+        path = '/%s/wibble/nip' % (BRANCH_ALIAS_PREFIX,)
         fault = self.codehosting_api.createBranch(owner.id, escape(path))
         message = "Cannot create linked branch at 'wibble/nip'."
         self.assertEqual(faults.PermissionDenied(message), fault)
@@ -631,7 +631,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # If the product series doesn't exist, we don't (yet) create it.
         owner = self.factory.makePerson()
         self.factory.makeProduct(name='wibble')
-        path = u'/%s/wibble/nip' % (BRANCH_ALIAS_PREFIX,)
+        path = '/%s/wibble/nip' % (BRANCH_ALIAS_PREFIX,)
         fault = self.codehosting_api.createBranch(owner.id, escape(path))
         message = "No such product series: 'nip'."
         self.assertEqual(faults.NotFound(message), fault)
@@ -777,19 +777,19 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # this happens, it returns a Fault saying so, including the path it
         # couldn't translate.
         requester = self.factory.makePerson()
-        path = escape(u'/untranslatable')
+        path = escape('/untranslatable')
         self.assertNotFound(requester, path)
 
     def test_translatePath_no_preceding_slash(self):
         requester = self.factory.makePerson()
-        path = escape(u'invalid')
+        path = escape('invalid')
         fault = self.codehosting_api.translatePath(requester.id, path)
         self.assertEqual(faults.InvalidPath(path), fault)
 
     def test_translatePath_branch(self):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch()
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -800,7 +800,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_branch_with_trailing_slash(self):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch()
-        path = escape(u'/%s/' % branch.unique_name)
+        path = escape('/%s/' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -811,7 +811,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_path_in_branch(self):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch()
-        path = escape(u'/%s/child' % branch.unique_name)
+        path = escape('/%s/child' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -822,7 +822,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_nested_path_in_branch(self):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch()
-        path = escape(u'/%s/a/b' % branch.unique_name)
+        path = escape('/%s/a/b' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -833,11 +833,11 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_preserves_escaping(self):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch()
-        child_path = u'a@b'
+        child_path = 'a@b'
         # This test is only meaningful if the path isn't the same when
         # escaped.
         self.assertNotEqual(escape(child_path), child_path.encode('utf-8'))
-        path = escape(u'/%s/%s' % (branch.unique_name, child_path))
+        path = escape('/%s/%s' % (branch.unique_name, child_path))
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -886,7 +886,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_no_such_branch_non_ascii(self):
         requester = self.factory.makePerson()
         product = self.factory.makeProduct()
-        path = u'/~%s/%s/non-asci\N{LATIN SMALL LETTER I WITH DIAERESIS}' % (
+        path = '/~%s/%s/non-asci\N{LATIN SMALL LETTER I WITH DIAERESIS}' % (
             requester.name, product.name)
         self.assertNotFound(requester, escape(path))
 
@@ -896,7 +896,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
             self.factory.makeAnyBranch(
                 branch_type=BranchType.HOSTED, owner=requester,
                 information_type=InformationType.USERDATA))
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -908,19 +908,19 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         requester = self.factory.makePerson()
         branch = removeSecurityProxy(self.factory.makeAnyBranch(
             information_type=InformationType.USERDATA))
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         self.assertPermissionDenied(requester, path)
 
     def test_translatePath_remote_branch(self):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch(branch_type=BranchType.REMOTE)
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         self.assertNotFound(requester, path)
 
     def test_translatePath_launchpad_services_private(self):
         branch = removeSecurityProxy(self.factory.makeAnyBranch(
             information_type=InformationType.USERDATA))
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(
             LAUNCHPAD_SERVICES, path)
         login(ANONYMOUS)
@@ -932,12 +932,12 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_anonymous_cant_see_private_branch(self):
         branch = removeSecurityProxy(self.factory.makeAnyBranch(
             information_type=InformationType.USERDATA))
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         self.assertPermissionDenied(LAUNCHPAD_ANONYMOUS, path)
 
     def test_translatePath_anonymous_public_branch(self):
         branch = self.factory.makeAnyBranch()
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(
             LAUNCHPAD_ANONYMOUS, path)
         self.assertEqual(
@@ -949,7 +949,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=requester)
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -962,7 +962,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         team = self.factory.makeTeam(requester)
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=team)
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -975,7 +975,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         team = self.factory.makeTeam(self.factory.makePerson())
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=team)
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -987,7 +987,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.MIRRORED, owner=requester)
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -999,7 +999,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         requester = self.factory.makePerson()
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.IMPORTED, owner=requester)
-        path = escape(u'/%s' % branch.unique_name)
+        path = escape('/%s' % branch.unique_name)
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertEqual(
@@ -1015,7 +1015,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         removeSecurityProxy(branch.product.development_focus).branch = branch
         short_name = ICanHasLinkedBranch(branch.product).bzr_path
         path_in_branch = '.bzr/branch-format'
-        path = escape(u'/%s' % os.path.join(
+        path = escape('/%s' % os.path.join(
                 BRANCH_ALIAS_PREFIX, short_name, path_in_branch))
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
@@ -1030,7 +1030,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         requester = self.factory.makePerson()
         branch = self.factory.makeBranch()
         path_in_branch = '.bzr/branch-format'
-        path = escape(u'/%s' % os.path.join(
+        path = escape('/%s' % os.path.join(
                 BRANCH_ALIAS_PREFIX, branch.unique_name, path_in_branch))
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
@@ -1147,7 +1147,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # Make sure the trailing path is returned.
         requester = self.factory.makePerson()
         branch = removeSecurityProxy(self.factory.makeAnyBranch())
-        path = escape(u'%s/foo/bar' % branch_id_alias(branch))
+        path = escape('%s/foo/bar' % branch_id_alias(branch))
         translation = self.codehosting_api.translatePath(requester.id, path)
         expected = (
             BRANCH_TRANSPORT,
@@ -1206,7 +1206,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
     def test_translatePath_control_directory(self):
         requester = self.factory.makePerson()
         product, branch = self._makeProductWithDevFocus()
-        path = escape(u'/~%s/%s/.bzr' % (requester.name, product.name))
+        path = escape('/~%s/%s/.bzr' % (requester.name, product.name))
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertTranslationIsControlDirectory(
@@ -1219,20 +1219,20 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         # don't even bother translating control directory paths.
         requester = self.factory.makePerson()
         product = self.factory.makeProduct()
-        path = escape(u'/~%s/%s/.bzr/' % (requester.name, product.name))
+        path = escape('/~%s/%s/.bzr/' % (requester.name, product.name))
         self.assertNotFound(requester, path)
 
     def test_translatePath_control_directory_invisble_branch(self):
         requester = self.factory.makePerson()
         product, branch = self._makeProductWithDevFocus(private=True)
-        path = escape(u'/~%s/%s/.bzr/' % (requester.name, product.name))
+        path = escape('/~%s/%s/.bzr/' % (requester.name, product.name))
         self.assertNotFound(requester, path)
 
     def test_translatePath_control_directory_private_branch(self):
         product, branch = self._makeProductWithDevFocus(private=True)
         branch = removeSecurityProxy(branch)
         requester = branch.owner
-        path = escape(u'/~%s/%s/.bzr/' % (requester.name, product.name))
+        path = escape('/~%s/%s/.bzr/' % (requester.name, product.name))
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertTranslationIsControlDirectory(
@@ -1244,7 +1244,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
         requester = self.factory.makePerson()
         product, branch = self._makeProductWithDevFocus()
         owner = self.factory.makePerson()
-        path = escape(u'/~%s/%s/.bzr' % (owner.name, product.name))
+        path = escape('/~%s/%s/.bzr' % (owner.name, product.name))
         translation = self.codehosting_api.translatePath(requester.id, path)
         login(ANONYMOUS)
         self.assertTranslationIsControlDirectory(
@@ -1291,7 +1291,7 @@ class AcquireBranchToPullTestsViaEndpoint(WithScenarios, TestCaseWithFactory,
         ]
 
     def setUp(self):
-        super(AcquireBranchToPullTestsViaEndpoint, self).setUp()
+        super().setUp()
         frontend = self.frontend()
         self.codehosting_api = frontend.getCodehostingEndpoint()
         self.factory = frontend.getLaunchpadObjectFactory()
diff --git a/lib/lp/code/xmlrpc/tests/test_git.py b/lib/lp/code/xmlrpc/tests/test_git.py
index 27c78c4..9dd57c1 100644
--- a/lib/lp/code/xmlrpc/tests/test_git.py
+++ b/lib/lp/code/xmlrpc/tests/test_git.py
@@ -138,7 +138,7 @@ class MatchesFault(MatchesStructure):
 
     def __init__(self, expected_fault):
         fault_matchers = {}
-        if (isinstance(expected_fault, six.class_types) and
+        if (isinstance(expected_fault, type) and
                 issubclass(expected_fault, faults.LaunchpadFault)):
             fault_matchers["faultCode"] = Equals(expected_fault.error_code)
         else:
@@ -146,17 +146,17 @@ class MatchesFault(MatchesStructure):
             fault_string = expected_fault.faultString
             # XXX cjwatson 2019-09-27: InvalidBranchName.faultString is
             # bytes, so we need this to handle that case.  Should it be?
-            if not isinstance(fault_string, six.text_type):
+            if not isinstance(fault_string, str):
                 fault_string = fault_string.decode("UTF-8")
             fault_matchers["faultString"] = Equals(fault_string)
-        super(MatchesFault, self).__init__(**fault_matchers)
+        super().__init__(**fault_matchers)
 
 
 class TestGitAPIMixin:
     """Helper methods for `IGitAPI` tests, and security-relevant tests."""
 
     def setUp(self):
-        super(TestGitAPIMixin, self).setUp()
+        super().setUp()
         self.git_api = xmlrpc.client.ServerProxy(
             "http://xmlrpc-private.launchpad.test:8087/git";,
             transport=XMLRPCTestTransport())
@@ -495,7 +495,7 @@ class TestGitAPIMixin:
         repository = removeSecurityProxy(
             self.factory.makeGitRepository(
                 owner=requester, information_type=InformationType.USERDATA))
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(requester, path, repository, True, private=True)
 
     def test_translatePath_cannot_see_private_repository(self):
@@ -503,14 +503,14 @@ class TestGitAPIMixin:
         repository = removeSecurityProxy(
             self.factory.makeGitRepository(
                 information_type=InformationType.USERDATA))
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertGitRepositoryNotFound(requester, path)
 
     def test_translatePath_anonymous_cannot_see_private_repository(self):
         repository = removeSecurityProxy(
             self.factory.makeGitRepository(
                 information_type=InformationType.USERDATA))
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertGitRepositoryNotFound(None, path, can_authenticate=False)
         self.assertUnauthorized(None, path, can_authenticate=True)
 
@@ -518,7 +518,7 @@ class TestGitAPIMixin:
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(self.factory.makePerson())
         repository = self.factory.makeGitRepository(owner=team)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(requester, path, repository, False)
         self.assertPermissionDenied(requester, path, permission="write")
 
@@ -526,7 +526,7 @@ class TestGitAPIMixin:
         requester = self.factory.makePerson()
         repository = self.factory.makeGitRepository(
             owner=requester, repository_type=GitRepositoryType.IMPORTED)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(requester, path, repository, False)
         self.assertPermissionDenied(requester, path, permission="write")
 
@@ -538,7 +538,7 @@ class TestGitAPIMixin:
         message = "%s is not a member of %s" % (
             requester.displayname, team.displayname)
         self.assertPermissionDenied(
-            requester, u"/~%s/+git/random" % team.name, message=message,
+            requester, "/~%s/+git/random" % team.name, message=message,
             permission="write")
 
     def test_translatePath_create_other_user(self):
@@ -547,7 +547,7 @@ class TestGitAPIMixin:
         other_person = self.factory.makePerson()
         project = self.factory.makeProduct()
         name = self.factory.getUniqueString()
-        path = u"/~%s/%s/+git/%s" % (other_person.name, project.name, name)
+        path = "/~%s/%s/+git/%s" % (other_person.name, project.name, name)
         message = "%s cannot create Git repositories owned by %s" % (
             requester.displayname, other_person.displayname)
         self.assertPermissionDenied(
@@ -558,7 +558,7 @@ class TestGitAPIMixin:
         # repository and immediately set it as the default for that project.
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
-        path = u"/%s" % project.name
+        path = "/%s" % project.name
         message = "%s cannot create Git repositories owned by %s" % (
             requester.displayname, project.owner.displayname)
         initial_count = getUtility(IAllGitRepositories).count()
@@ -577,7 +577,7 @@ class TestGitAPIMixin:
         distribution = self.factory.makeDistribution(
             oci_project_admin=self.factory.makeTeam())
         oci_project = self.factory.makeOCIProject(pillar=distribution)
-        path = u"/%s/+oci/%s" % (oci_project.pillar.name, oci_project.name)
+        path = "/%s/+oci/%s" % (oci_project.pillar.name, oci_project.name)
         message = "%s is not a member of %s" % (
             requester.displayname,
             oci_project.pillar.oci_project_admin.displayname)
@@ -594,11 +594,11 @@ class TestGitAPIMixin:
         other_person = self.factory.makePerson()
         repository = self.factory.makeGitRepository(owner=requester)
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/stable/next')
+            repository, ref_pattern='refs/heads/stable/next')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=other_person,
             can_force_push=True)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(
             other_person, path, repository, True, private=False)
 
@@ -608,11 +608,11 @@ class TestGitAPIMixin:
         other_person = self.factory.makePerson()
         repository = self.factory.makeGitRepository(owner=requester)
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/stable/next')
+            repository, ref_pattern='refs/heads/stable/next')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=grant_person,
             can_force_push=True)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(
             other_person, path, repository, False, private=False)
 
@@ -623,11 +623,11 @@ class TestGitAPIMixin:
             self.factory.makeGitRepository(
                 owner=requester, information_type=InformationType.USERDATA))
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/stable/next')
+            repository, ref_pattern='refs/heads/stable/next')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=other_person,
             can_force_push=True)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertGitRepositoryNotFound(
             other_person, path, can_authenticate=True)
 
@@ -642,34 +642,34 @@ class TestGitAPIMixin:
             self.factory.makeGitRepository(owner=user_a))
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/stable/next')
+            repository, ref_pattern='refs/heads/stable/next')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=GitGranteeType.REPOSITORY_OWNER,
             can_force_push=True)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/stable/protected')
+            repository, ref_pattern='refs/heads/stable/protected')
         self.factory.makeGitRuleGrant(rule=rule, grantee=stable_team)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/archived/*')
+            repository, ref_pattern='refs/heads/archived/*')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=GitGranteeType.REPOSITORY_OWNER)
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=user_b, can_create=True)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/stable/*')
+            repository, ref_pattern='refs/heads/stable/*')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=stable_team, can_push=True)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/*/next')
+            repository, ref_pattern='refs/heads/*/next')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=next_team, can_force_push=True)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/tags/*')
+            repository, ref_pattern='refs/tags/*')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=GitGranteeType.REPOSITORY_OWNER,
             can_create=True)
@@ -743,18 +743,18 @@ class TestGitAPIMixin:
             self.factory.makeGitRepository(owner=user_a))
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/master')
+            repository, ref_pattern='refs/heads/master')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=user_b, can_push=True)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/heads/*')
+            repository, ref_pattern='refs/heads/*')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=GitGranteeType.REPOSITORY_OWNER,
             can_create=True, can_push=True, can_force_push=True)
 
         rule = self.factory.makeGitRule(
-            repository, ref_pattern=u'refs/tags/*')
+            repository, ref_pattern='refs/tags/*')
         self.factory.makeGitRuleGrant(
             rule=rule, grantee=user_b, can_push=True)
 
@@ -797,11 +797,11 @@ class TestGitAPIMixin:
         repository = removeSecurityProxy(
             self.factory.makeGitRepository(owner=owner))
         self.factory.makeGitRuleGrant(
-            repository=repository, ref_pattern=u"refs/heads/next/*",
+            repository=repository, ref_pattern="refs/heads/next/*",
             grantee=grantee, can_push=True)
         paths = [
             # Properly-encoded UTF-8.
-            u"refs/heads/next/\N{BLACK HEART SUIT}".encode("UTF-8"),
+            "refs/heads/next/\N{BLACK HEART SUIT}".encode(),
             # Non-UTF-8.  (git does not require any particular encoding for
             # ref paths; non-UTF-8 ones won't work well everywhere, but it's
             # at least possible to round-trip them through Launchpad.)
@@ -1211,12 +1211,12 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # When this happens, it returns a Fault saying so, including the
         # path it couldn't translate.
         requester = self.factory.makePerson()
-        self.assertGitRepositoryNotFound(requester, u"/untranslatable")
+        self.assertGitRepositoryNotFound(requester, "/untranslatable")
 
     def test_translatePath_repository(self):
         requester = self.factory.makePerson()
         repository = self.factory.makeGitRepository()
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(requester, path, repository, False)
 
     def test_translatePath_repository_with_no_leading_slash(self):
@@ -1228,30 +1228,30 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
     def test_translatePath_repository_with_trailing_slash(self):
         requester = self.factory.makePerson()
         repository = self.factory.makeGitRepository()
-        path = u"/%s/" % repository.unique_name
+        path = "/%s/" % repository.unique_name
         self.assertTranslates(requester, path, repository, False)
 
     def test_translatePath_repository_with_trailing_segments(self):
         requester = self.factory.makePerson()
         repository = self.factory.makeGitRepository()
-        path = u"/%s/foo/bar" % repository.unique_name
+        path = "/%s/foo/bar" % repository.unique_name
         self.assertTranslates(
             requester, path, repository, False, trailing="foo/bar")
 
     def test_translatePath_no_such_repository(self):
         requester = self.factory.makePerson()
-        path = u"/%s/+git/no-such-repository" % requester.name
+        path = "/%s/+git/no-such-repository" % requester.name
         self.assertGitRepositoryNotFound(requester, path)
 
     def test_translatePath_no_such_repository_non_ascii(self):
         requester = self.factory.makePerson()
-        path = u"/%s/+git/\N{LATIN SMALL LETTER I WITH DIAERESIS}" % (
+        path = "/%s/+git/\N{LATIN SMALL LETTER I WITH DIAERESIS}" % (
             requester.name)
         self.assertGitRepositoryNotFound(requester, path)
 
     def test_translatePath_anonymous_public_repository(self):
         repository = self.factory.makeGitRepository()
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(
             None, path, repository, False, can_authenticate=False)
         self.assertTranslates(
@@ -1260,7 +1260,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
     def test_translatePath_owned(self):
         requester = self.factory.makePerson()
         repository = self.factory.makeGitRepository(owner=requester)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(
             requester, path, repository, True, permission="write")
 
@@ -1268,7 +1268,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(requester)
         repository = self.factory.makeGitRepository(owner=team)
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         self.assertTranslates(
             requester, path, repository, True, permission="write")
 
@@ -1279,7 +1279,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         with person_logged_in(repository.target.owner):
             getUtility(IGitRepositorySet).setDefaultRepository(
                 repository.target, repository)
-        path = u"/%s" % repository.target.name
+        path = "/%s" % repository.target.name
         self.assertTranslates(requester, path, repository, False)
 
     def test_translatePath_create_project_async(self):
@@ -1288,14 +1288,14 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
         self.assertCreates(
-            requester, u"/~%s/%s/+git/random" % (requester.name, project.name))
+            requester, "/~%s/%s/+git/random" % (requester.name, project.name))
 
     def test_translatePath_create_project_sync(self):
         self.useFixture(FeatureFixture({GIT_ASYNC_CREATE_REPO: ''}))
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
         self.assertCreates(
-            requester, u"/~%s/%s/+git/random" % (requester.name, project.name),
+            requester, "/~%s/%s/+git/random" % (requester.name, project.name),
             async_create=False)
 
     def test_translatePath_create_project_blocks_duplicate_calls(self):
@@ -1303,7 +1303,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # but blocks any further request to create the same repository.
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
-        path = u"/~%s/%s/+git/random" % (requester.name, project.name)
+        path = "/~%s/%s/+git/random" % (requester.name, project.name)
         self.assertCreates(requester, path)
 
         auth_params = _make_auth_params(
@@ -1323,7 +1323,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
             self.repository_set.setDefaultRepository(target, repository)
             self.assertCreatesFromClone(
                 target.owner,
-                u"/~%s/%s/+git/random" % (target.owner.name, target.name),
+                "/~%s/%s/+git/random" % (target.owner.name, target.name),
                 repository)
 
     def test_translatePath_create_project_clone_from_owner_default(self):
@@ -1337,7 +1337,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
                 target.owner, target, repository, user)
             self.assertCreatesFromClone(
                 target.owner,
-                u"/~%s/%s/+git/random" % (target.owner.name, target.name),
+                "/~%s/%s/+git/random" % (target.owner.name, target.name),
                 repository)
 
     def test_translatePath_create_package(self):
@@ -1347,7 +1347,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         dsp = self.factory.makeDistributionSourcePackage()
         self.assertCreates(
             requester,
-            u"/~%s/%s/+source/%s/+git/random" % (
+            "/~%s/%s/+source/%s/+git/random" % (
                 requester.name,
                 dsp.distribution.name, dsp.sourcepackagename.name))
 
@@ -1358,45 +1358,45 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         oci_project = self.factory.makeOCIProject()
         self.assertCreates(
             requester,
-            u"/~%s/%s/+oci/%s/+git/random" % (
+            "/~%s/%s/+oci/%s/+git/random" % (
                 requester.name, oci_project.pillar.name, oci_project.name))
 
     def test_translatePath_create_personal(self):
         # translatePath creates a personal repository that doesn't exist, if
         # it can.
         requester = self.factory.makePerson()
-        self.assertCreates(requester, u"/~%s/+git/random" % requester.name)
+        self.assertCreates(requester, "/~%s/+git/random" % requester.name)
 
     def test_translatePath_create_personal_team(self):
         # translatePath creates a personal repository for a team of which
         # the requester is a member.
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(members=[requester])
-        self.assertCreates(requester, u"/~%s/+git/random" % team.name)
+        self.assertCreates(requester, "/~%s/+git/random" % team.name)
 
     def test_translatePath_create_native_string(self):
         # On Python 2, ASCII strings come in as native strings, not Unicode
         # strings. They work fine too.
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
-        path = u"/~%s/%s/+git/random" % (requester.name, project.name)
+        path = "/~%s/%s/+git/random" % (requester.name, project.name)
         self.assertCreates(requester, six.ensure_str(path))
 
     def test_translatePath_anonymous_cannot_create(self):
         # Anonymous users cannot create repositories.
         project = self.factory.makeProject()
         self.assertGitRepositoryNotFound(
-            None, u"/%s" % project.name, permission="write",
+            None, "/%s" % project.name, permission="write",
             can_authenticate=False)
         self.assertUnauthorized(
-            None, u"/%s" % project.name, permission="write",
+            None, "/%s" % project.name, permission="write",
             can_authenticate=True)
 
     def test_translatePath_create_invalid_namespace(self):
         # Trying to create a repository at a path that isn't valid for Git
         # repositories returns a PermissionDenied fault.
         requester = self.factory.makePerson()
-        path = u"/~%s" % requester.name
+        path = "/~%s" % requester.name
         message = "'%s' is not a valid Git repository path." % path.strip("/")
         self.assertPermissionDenied(
             requester, path, message=message, permission="write")
@@ -1405,14 +1405,14 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # Creating a repository for a non-existent person fails.
         requester = self.factory.makePerson()
         self.assertNotFound(
-            requester, u"/~nonexistent/+git/random",
+            requester, "/~nonexistent/+git/random",
             "User/team 'nonexistent' does not exist.", permission="write")
 
     def test_translatePath_create_no_such_project(self):
         # Creating a repository for a non-existent project fails.
         requester = self.factory.makePerson()
         self.assertNotFound(
-            requester, u"/~%s/nonexistent/+git/random" % requester.name,
+            requester, "/~%s/nonexistent/+git/random" % requester.name,
             "Project 'nonexistent' does not exist.", permission="write")
 
     def test_translatePath_create_no_such_person_or_project(self):
@@ -1420,14 +1420,14 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # person is reported in preference.
         requester = self.factory.makePerson()
         self.assertNotFound(
-            requester, u"/~nonexistent/nonexistent/+git/random",
+            requester, "/~nonexistent/nonexistent/+git/random",
             "User/team 'nonexistent' does not exist.", permission="write")
 
     def test_translatePath_create_invalid_project(self):
         # Creating a repository with an invalid project name fails.
         requester = self.factory.makePerson()
         self.assertNotFound(
-            requester, u"/_bad_project/+git/random",
+            requester, "/_bad_project/+git/random",
             "Project '_bad_project' does not exist.", permission="write")
 
     def test_translatePath_create_missing_sourcepackagename(self):
@@ -1436,7 +1436,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         distro = self.factory.makeDistribution()
         repository_name = self.factory.getUniqueString()
-        path = u"/~%s/%s/+source/new-package/+git/%s" % (
+        path = "/~%s/%s/+source/new-package/+git/%s" % (
             requester.name, distro.name, repository_name)
         repository = self.assertCreates(requester, path)
         self.assertEqual(
@@ -1447,7 +1447,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         distro = self.factory.makeDistribution()
         repository_name = self.factory.getUniqueString()
-        path = u"/~%s/%s/+source/new package/+git/%s" % (
+        path = "/~%s/%s/+source/new package/+git/%s" % (
             requester.name, distro.name, repository_name)
         self.assertInvalidSourcePackageName(
             requester, path, "new package", permission="write")
@@ -1457,7 +1457,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
         invalid_name = "invalid name!"
-        path = u"/~%s/%s/+git/%s" % (
+        path = "/~%s/%s/+git/%s" % (
             requester.name, project.name, invalid_name)
         # LaunchpadValidationError unfortunately assumes its output is
         # always HTML, so it ends up double-escaped in XML-RPC faults.
@@ -1471,8 +1471,8 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # Creating a repository with a non-ASCII invalid name fails.
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
-        invalid_name = u"invalid\N{LATIN SMALL LETTER E WITH ACUTE}"
-        path = u"/~%s/%s/+git/%s" % (
+        invalid_name = "invalid\N{LATIN SMALL LETTER E WITH ACUTE}"
+        path = "/~%s/%s/+git/%s" % (
             requester.name, project.name, invalid_name)
         # LaunchpadValidationError unfortunately assumes its output is
         # always HTML, so it ends up double-escaped in XML-RPC faults.
@@ -1490,7 +1490,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
             membership_policy=TeamMembershipPolicy.RESTRICTED,
             members=[requester])
         project = self.factory.makeProduct(owner=owner)
-        repository = self.assertCreates(requester, u"/%s" % project.name)
+        repository = self.assertCreates(requester, "/%s" % project.name)
         self.assertTrue(repository.target_default)
         self.assertTrue(repository.owner_default)
         self.assertEqual(owner, repository.owner)
@@ -1500,7 +1500,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # default for a package.
         requester = self.factory.makePerson()
         dsp = self.factory.makeDistributionSourcePackage()
-        path = u"/%s/+source/%s" % (
+        path = "/%s/+source/%s" % (
             dsp.distribution.name, dsp.sourcepackagename.name)
         message = (
             "Cannot automatically set the default repository for this target; "
@@ -1518,7 +1518,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         oci_project = self.factory.makeOCIProject(pillar=distribution)
         repository = self.assertCreates(
             requester,
-            u"/%s/+oci/%s" % (oci_project.pillar.name, oci_project.name))
+            "/%s/+oci/%s" % (oci_project.pillar.name, oci_project.name))
         self.assertTrue(repository.target_default)
         self.assertTrue(repository.owner_default)
         self.assertEqual(oci_project_admin, repository.owner)
@@ -1529,7 +1529,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # default for that OCI project.
         requester = self.factory.makePerson()
         oci_project = self.factory.makeOCIProject()
-        path = u"/%s/+oci/%s" % (oci_project.pillar.name, oci_project.name)
+        path = "/%s/+oci/%s" % (oci_project.pillar.name, oci_project.name)
         message = (
             "Cannot automatically set the default repository for this target; "
             "push to a named repository instead.")
@@ -1547,7 +1547,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         project = self.factory.makeProduct()
         repository = self.assertCreates(
-            requester, u"/~%s/%s" % (requester.name, project.name))
+            requester, "/~%s/%s" % (requester.name, project.name))
         self.assertFalse(repository.target_default)
         self.assertTrue(repository.owner_default)
         self.assertEqual(requester, repository.owner)
@@ -1559,7 +1559,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         team = self.factory.makeTeam(owner=requester)
         project = self.factory.makeProduct()
         repository = self.assertCreates(
-            requester, u"/~%s/%s" % (team.name, project.name))
+            requester, "/~%s/%s" % (team.name, project.name))
         self.assertFalse(repository.target_default)
         self.assertTrue(repository.owner_default)
         self.assertEqual(team, repository.owner)
@@ -1571,7 +1571,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         team = self.factory.makeTeam(members=[requester])
         project = self.factory.makeProduct()
         repository = self.assertCreates(
-            requester, u"/~%s/%s" % (team.name, project.name))
+            requester, "/~%s/%s" % (team.name, project.name))
         self.assertFalse(repository.target_default)
         self.assertTrue(repository.owner_default)
         self.assertEqual(team, repository.owner)
@@ -1581,7 +1581,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # default for a package.
         requester = self.factory.makePerson()
         dsp = self.factory.makeDistributionSourcePackage()
-        path = u"/~%s/%s/+source/%s" % (
+        path = "/~%s/%s/+source/%s" % (
             requester.name, dsp.distribution.name, dsp.sourcepackagename.name)
         repository = self.assertCreates(requester, path)
         self.assertFalse(repository.target_default)
@@ -1594,7 +1594,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(owner=requester)
         dsp = self.factory.makeDistributionSourcePackage()
-        path = u"/~%s/%s/+source/%s" % (
+        path = "/~%s/%s/+source/%s" % (
             team.name, dsp.distribution.name, dsp.sourcepackagename.name)
         repository = self.assertCreates(requester, path)
         self.assertFalse(repository.target_default)
@@ -1607,7 +1607,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(members=[requester])
         dsp = self.factory.makeDistributionSourcePackage()
-        path = u"/~%s/%s/+source/%s" % (
+        path = "/~%s/%s/+source/%s" % (
             team.name, dsp.distribution.name, dsp.sourcepackagename.name)
         repository = self.assertCreates(requester, path)
         self.assertFalse(repository.target_default)
@@ -1619,7 +1619,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # default for an OCI project.
         requester = self.factory.makePerson()
         oci_project = self.factory.makeOCIProject()
-        path = u"/~%s/%s/+oci/%s" % (
+        path = "/~%s/%s/+oci/%s" % (
             requester.name, oci_project.pillar.name, oci_project.name)
         repository = self.assertCreates(requester, path)
         self.assertFalse(repository.target_default)
@@ -1632,7 +1632,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(owner=requester)
         oci_project = self.factory.makeOCIProject()
-        path = u"/~%s/%s/+oci/%s" % (
+        path = "/~%s/%s/+oci/%s" % (
             team.name, oci_project.pillar.name, oci_project.name)
         repository = self.assertCreates(requester, path)
         self.assertFalse(repository.target_default)
@@ -1645,7 +1645,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         team = self.factory.makeTeam(members=[requester])
         oci_project = self.factory.makeOCIProject()
-        path = u"/~%s/%s/+oci/%s" % (
+        path = "/~%s/%s/+oci/%s" % (
             team.name, oci_project.pillar.name, oci_project.name)
         repository = self.assertCreates(requester, path)
         self.assertFalse(repository.target_default)
@@ -1661,7 +1661,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester = self.factory.makePerson()
         initial_count = getUtility(IAllGitRepositories).count()
         oops_id = self.assertOopsOccurred(
-            requester, u"/~%s/+git/random" % requester.name,
+            requester, "/~%s/+git/random" % requester.name,
             permission="write")
         login(ANONYMOUS)
         self.assertEqual(
@@ -1691,7 +1691,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         issuer = getUtility(IMacaroonIssuer, "code-import-job")
         macaroons = [
             removeSecurityProxy(issuer).issueMacaroon(job) for job in jobs]
-        path = u"/%s" % code_imports[0].git_repository.unique_name
+        path = "/%s" % code_imports[0].git_repository.unique_name
         self.assertUnauthorized(
             LAUNCHPAD_SERVICES, path, permission="write",
             macaroon_raw=macaroons[0].serialize())
@@ -1735,7 +1735,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         issuer = getUtility(IMacaroonIssuer, "code-import-job")
         macaroons = [
             removeSecurityProxy(issuer).issueMacaroon(job) for job in jobs]
-        path = u"/%s" % code_imports[0].git_repository.unique_name
+        path = "/%s" % code_imports[0].git_repository.unique_name
         self.assertUnauthorized(
             LAUNCHPAD_SERVICES, path, permission="write",
             macaroon_raw=macaroons[0].serialize())
@@ -1780,7 +1780,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
                 removeSecurityProxy(issuer).issueMacaroon(build)
                 for build in builds]
             repository = refs[0].repository
-            path = u"/%s" % repository.unique_name
+            path = "/%s" % repository.unique_name
         self.assertUnauthorized(
             LAUNCHPAD_SERVICES, path, permission="write",
             macaroon_raw=macaroons[0].serialize())
@@ -1819,7 +1819,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
                     repository, user=requester)
                 for repository in repositories]
             paths = [
-                u"/%s" % repository.unique_name for repository in repositories]
+                "/%s" % repository.unique_name for repository in repositories]
         for i, repository in enumerate(repositories):
             for j, macaroon in enumerate(macaroons):
                 login(ANONYMOUS)
@@ -1853,7 +1853,7 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         self.useFixture(ZopeUtilityFixture(
             issuer, IMacaroonIssuer, name="test"))
         repository = self.factory.makeGitRepository()
-        path = u"/%s" % repository.unique_name
+        path = "/%s" % repository.unique_name
         macaroon = issuer.issueMacaroon(repository)
         requesters = [self.factory.makePerson() for _ in range(2)]
         for verified_user, authorized, unauthorized in (
@@ -1881,8 +1881,8 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         requester_owner = self.factory.makePerson()
         repository = self.factory.makeGitRepository(owner=requester_owner)
         self.factory.makeGitRefs(
-            repository=repository, paths=[u'refs/heads/master'])
-        removeSecurityProxy(repository).default_branch = u'refs/heads/master'
+            repository=repository, paths=['refs/heads/master'])
+        removeSecurityProxy(repository).default_branch = 'refs/heads/master'
         pushed_branch = 'branch1'
         self.assertHasMergeProposalURL(repository, pushed_branch,
                                        {"uid": requester_owner.id})
@@ -1892,9 +1892,9 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         # Consequently LP will process any incoming branch from Turnip
         # as being non default and produce a merge proposal URL for it.
         self.factory.makeGitRefs(
-            repository=repository, paths=[u'refs/heads/%s' % pushed_branch])
+            repository=repository, paths=['refs/heads/%s' % pushed_branch])
         removeSecurityProxy(repository).default_branch = (
-                u'refs/heads/%s' % pushed_branch)
+                'refs/heads/%s' % pushed_branch)
         self.assertHasMergeProposalURL(repository, pushed_branch,
                                        {"uid": requester_owner.id})
 
@@ -1912,8 +1912,8 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         repository = self.factory.makeGitRepository(owner=requester)
         issuer = getUtility(IMacaroonIssuer, "git-repository")
         self.factory.makeGitRefs(
-            repository=repository, paths=[u'refs/heads/master'])
-        removeSecurityProxy(repository).default_branch = u'refs/heads/master'
+            repository=repository, paths=['refs/heads/master'])
+        removeSecurityProxy(repository).default_branch = 'refs/heads/master'
 
         pushed_branch = 'branch1'
         with person_logged_in(requester):
@@ -1940,8 +1940,8 @@ class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory):
         owner = self.factory.makeTeam(members=requesters)
         repository = self.factory.makeGitRepository(owner=owner)
         self.factory.makeGitRefs(
-            repository=repository, paths=[u'refs/heads/master'])
-        removeSecurityProxy(repository).default_branch = u'refs/heads/master'
+            repository=repository, paths=['refs/heads/master'])
+        removeSecurityProxy(repository).default_branch = 'refs/heads/master'
         pushed_branch = 'branch1'
         macaroon = issuer.issueMacaroon(repository)