← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Commit message:
Apply "pyupgrade --py3-plus" to most remaining files

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

There are a couple of non-production scripts in `utilities/` and their dependencies that still require Python 2, as well as the code in `lib/contrib/` that's copied from elsewhere pending replacement by dependencies from PyPI and that's better to leave alone.  Everything else that `pyupgrade` knows how to deal with now uses Python 3 syntax.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:pyupgrade-py3-remaining into launchpad:master.
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a64bbd3..80c13da 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -32,36 +32,14 @@ repos:
     rev: v2.31.0
     hooks:
     -   id: pyupgrade
-        args: [--keep-percent-format]
-        exclude: ^lib/contrib/
-    -   id: pyupgrade
-        alias: pyupgrade-py3
-        name: pyupgrade (--py3-plus)
         args: [--keep-percent-format, --py3-plus]
-        files: |
-          (?x)^lib/lp/(
-            answers
-            |app
-            |archivepublisher
-            |archiveuploader
-            |blueprints
-            |bugs
-            |buildmaster
-            |charms
-            |code
-            |codehosting
-            |coop
-            |oci
-            |registry
-            |scripts
-            |services
-            |snappy
-            |soyuz
-            |testing
-            |testopenid
-            |tests
-            |translations
-          )/
+        exclude: |
+          (?x)^(
+            lib/contrib/.*
+            |lib/devscripts/.*
+            |utilities/community-contributions\.py
+            |utilities/update-sourcecode
+          )$
 -   repo: https://github.com/PyCQA/isort
     rev: 5.9.2
     hooks:
diff --git a/brzplugins/lpserve/__init__.py b/brzplugins/lpserve/__init__.py
index 52ce8ac..6b47fde 100644
--- a/brzplugins/lpserve/__init__.py
+++ b/brzplugins/lpserve/__init__.py
@@ -29,7 +29,6 @@ from breezy.transport import (
     get_transport,
     transport_server_registry,
     )
-import six
 
 
 class cmd_launchpad_server(Command):
@@ -56,7 +55,7 @@ class cmd_launchpad_server(Command):
             help=(
                 "upload branches to this directory. Defaults to "
                 "config.codehosting.hosted_branches_root."),
-            type=six.text_type),
+            type=str),
         Option(
             'mirror-directory',
             help=(
@@ -67,7 +66,7 @@ class cmd_launchpad_server(Command):
             help=(
                 "the url of the internal XML-RPC server. Defaults to "
                 "config.codehosting.codehosting_endpoint."),
-            type=six.text_type),
+            type=str),
         RegistryOption(
             'protocol', help="Protocol to serve.",
             lazy_registry=('breezy.transport', 'transport_server_registry'),
diff --git a/brzplugins/lpserve/test_lpserve.py b/brzplugins/lpserve/test_lpserve.py
index a9563ec..1ce8641 100644
--- a/brzplugins/lpserve/test_lpserve.py
+++ b/brzplugins/lpserve/test_lpserve.py
@@ -8,7 +8,6 @@ from breezy import (
     osutils,
     tests,
     )
-import six
 
 from lp.codehosting import (
     get_brz_path,
@@ -43,11 +42,11 @@ class TestCaseWithSubprocess(tests.TestCaseWithTransport):
         old_env = {}
 
         def cleanup_environment():
-            for env_var, value in six.iteritems(env_changes):
+            for env_var, value in env_changes.items():
                 old_env[env_var] = osutils.set_or_unset_env(env_var, value)
 
         def restore_environment():
-            for env_var, value in six.iteritems(old_env):
+            for env_var, value in old_env.items():
                 osutils.set_or_unset_env(env_var, value)
 
         cwd = None
diff --git a/cronscripts/librarian-feed-swift.py b/cronscripts/librarian-feed-swift.py
index ae60177..8e4bba3 100755
--- a/cronscripts/librarian-feed-swift.py
+++ b/cronscripts/librarian-feed-swift.py
@@ -9,8 +9,6 @@ import _pythonpath  # noqa: F401
 
 import os
 
-import six
-
 from lp.services.database.interfaces import ISlaveStore
 from lp.services.librarian.model import LibraryFileContent
 from lp.services.librarianserver import swift
@@ -79,14 +77,14 @@ class LibrarianFeedSwift(LaunchpadCronScript):
                 SELECT MAX(id) FROM LibraryFileContent
                 WHERE datecreated < current_timestamp at time zone 'UTC'
                     - CAST(%s AS INTERVAL)
-                """, (six.text_type(self.options.start_since),)).get_one()[0]
+                """, (str(self.options.start_since),)).get_one()[0]
 
         if self.options.end_at:
             self.options.end = ISlaveStore(LibraryFileContent).execute("""
                 SELECT MAX(id) FROM LibraryFileContent
                 WHERE datecreated < current_timestamp at time zone 'UTC'
                     - CAST(%s AS INTERVAL)
-                """, (six.text_type(self.options.end_at),)).get_one()[0]
+                """, (str(self.options.end_at),)).get_one()[0]
 
         if ((self.options.instance_id is None) !=
                 (self.options.num_instances is None)):
diff --git a/database/schema/security.py b/database/schema/security.py
index 06bdc23..7281678 100755
--- a/database/schema/security.py
+++ b/database/schema/security.py
@@ -12,8 +12,6 @@ import os
 import re
 import sys
 
-import six
-
 from fti import quote_identifier
 from lp.services.database.sqlbase import connect
 from lp.services.scripts import (
@@ -117,7 +115,7 @@ def list_role_members(cur, roles):
     return members
 
 
-class DbObject(object):
+class DbObject:
 
     def __init__(
         self, schema, name, type_, owner, acl, arguments=None, language=None):
@@ -151,7 +149,7 @@ class DbObject(object):
 
 class DbSchema(dict):
     def __init__(self, con):
-        super(DbSchema, self).__init__()
+        super().__init__()
         cur = con.cursor()
         log.debug("Getting relation metadata")
         cur.execute('''
@@ -223,7 +221,7 @@ class DbSchema(dict):
             for r in cur.fetchall()}
 
 
-class CursorWrapper(object):
+class CursorWrapper:
 
     def __init__(self, cursor):
         self.__dict__['_cursor'] = cursor
@@ -306,8 +304,8 @@ class PermissionGatherer:
             to grant or revoke for.  Each is a string.
         """
         result = []
-        for permission, parties in six.iteritems(self.permissions):
-            for principal, entities in six.iteritems(parties):
+        for permission, parties in self.permissions.items():
+            for principal, entities in parties.items():
                 result.append(
                     (permission, ", ".join(entities), principal))
         return result
@@ -319,8 +317,8 @@ class PermissionGatherer:
     def countEntities(self):
         """Count the number of different entities."""
         entities = set()
-        for entities_and_entities in six.itervalues(self.permissions):
-            for extra_entities in six.itervalues(entities_and_entities):
+        for entities_and_entities in self.permissions.values():
+            for extra_entities in entities_and_entities.values():
                 entities.update(extra_entities)
         return len(entities)
 
@@ -328,7 +326,7 @@ class PermissionGatherer:
         """Count the number of different principals."""
         return len(set(sum((
             list(principals)
-            for principals in six.itervalues(self.permissions)), [])))
+            for principals in self.permissions.values()), [])))
 
     def grant(self, cur):
         """Grant all gathered permissions.
@@ -484,7 +482,7 @@ def reset_permissions(con, config, options):
 
     log.debug('Updating group memberships')
     existing_memberships = list_role_members(cur, list(memberships))
-    for group, users in six.iteritems(memberships):
+    for group, users in memberships.items():
         cur_users = managed_roles.intersection(existing_memberships[group])
         to_grant = users - cur_users
         if to_grant:
@@ -622,7 +620,7 @@ def reset_permissions(con, config, options):
             new = desired_permissions[obj][role]
             old_privs = obj.acl.get(role, {})
             old = set(old_privs)
-            if any(six.itervalues(old_privs)):
+            if any(old_privs.values()):
                 log.warning("%s has grant option on %s", role, obj.fullname)
             if new == old:
                 continue
diff --git a/database/schema/upgrade.py b/database/schema/upgrade.py
index bab20e3..3b579ff 100755
--- a/database/schema/upgrade.py
+++ b/database/schema/upgrade.py
@@ -180,7 +180,7 @@ def get_patchlist(con):
             log.fatal('Invalid patch filename %s' % repr(patch_file))
             raise SystemExit(1)
 
-        major, minor, patch = [int(i) for i in m.groups()]
+        major, minor, patch = (int(i) for i in m.groups())
         if (major, minor, patch) in dbpatches:
             continue  # This patch has already been applied
         log.debug("Found patch %d.%d.%d -- %s" % (
diff --git a/lib/launchpad_loggerhead/app.py b/lib/launchpad_loggerhead/app.py
index aa58d54..7ada98a 100644
--- a/lib/launchpad_loggerhead/app.py
+++ b/lib/launchpad_loggerhead/app.py
@@ -120,8 +120,7 @@ class RootApp:
         """
         openid_request = self._make_consumer(environ).begin(
             config.launchpad.openid_provider_root)
-        openid_request.addExtension(
-            SRegRequest(required=[u'nickname']))
+        openid_request.addExtension(SRegRequest(required=['nickname']))
         back_to = construct_url(environ)
         raise HTTPMovedPermanently(openid_request.redirectURL(
             config.codehosting.secure_codebrowse_root,
diff --git a/lib/launchpad_loggerhead/session.py b/lib/launchpad_loggerhead/session.py
index 2adb69c..ce214f7 100644
--- a/lib/launchpad_loggerhead/session.py
+++ b/lib/launchpad_loggerhead/session.py
@@ -21,7 +21,7 @@ class LaunchpadSecureCookie(SecureCookie):
     hash_method = staticmethod(hashlib.sha256)
 
     # The OpenID consumer stores non-JSON-encodable objects in the session.
-    class serialization_method(object):
+    class serialization_method:
 
         @classmethod
         def dumps(cls, value):
@@ -33,7 +33,7 @@ class LaunchpadSecureCookie(SecureCookie):
             return pickle.loads(value)
 
 
-class SessionHandler(object):
+class SessionHandler:
     """Middleware that provides a cookie-based session.
 
     The session dict is stored, pickled (and HMACed), in a cookie, so don't
diff --git a/lib/launchpad_loggerhead/tests.py b/lib/launchpad_loggerhead/tests.py
index 1c78b51..cad2ec3 100644
--- a/lib/launchpad_loggerhead/tests.py
+++ b/lib/launchpad_loggerhead/tests.py
@@ -128,7 +128,7 @@ class TestWSGI(TestCaseWithFactory):
     layer = AppServerLayer
 
     def setUp(self):
-        super(TestWSGI, self).setUp()
+        super().setUp()
         self.useBzrBranches()
         loggerhead_fixture = self.useFixture(LoggerheadFixture())
 
@@ -136,7 +136,7 @@ class TestWSGI(TestCaseWithFactory):
             try:
                 with open(loggerhead_fixture.logfile, "rb") as logfile:
                     return [logfile.read()]
-            except IOError:
+            except OSError:
                 return [b""]
 
         self.addDetail(
diff --git a/lib/launchpad_loggerhead/wsgi.py b/lib/launchpad_loggerhead/wsgi.py
index 633fb7c..eefe119 100644
--- a/lib/launchpad_loggerhead/wsgi.py
+++ b/lib/launchpad_loggerhead/wsgi.py
@@ -92,7 +92,7 @@ def log_request_start_and_stop(app):
 class LoggerheadLogger(Logger):
 
     def setup(self, cfg):
-        super(LoggerheadLogger, self).setup(cfg)
+        super().setup(cfg)
         formatter = LaunchpadFormatter(datefmt=None)
         for handler in self.error_log.handlers:
             handler.setFormatter(formatter)
@@ -120,7 +120,7 @@ class LoggerheadApplication(Application):
 
     def __init__(self, **kwargs):
         self.options = kwargs
-        super(LoggerheadApplication, self).__init__()
+        super().__init__()
 
     def init(self, parser, opts, args):
         top = os.path.abspath(os.path.join(
diff --git a/lib/lp/security.py b/lib/lp/security.py
index 5e74fd5..7d5c7d9 100644
--- a/lib/lp/security.py
+++ b/lib/lp/security.py
@@ -468,7 +468,7 @@ class ViewAccount(EditAccountBySelfOrAdmin):
     def checkAuthenticated(self, user):
         """Extend permission to registry experts."""
         return (
-            super(ViewAccount, self).checkAuthenticated(user)
+            super().checkAuthenticated(user)
             or user.in_registry_experts)
 
 
@@ -544,7 +544,7 @@ class LimitedViewProduct(ViewProduct):
 
     def checkAuthenticated(self, user):
         return (
-            super(LimitedViewProduct, self).checkAuthenticated(user) or
+            super().checkAuthenticated(user) or
             self.obj.userCanLimitedView(user))
 
 
@@ -554,7 +554,7 @@ class EditProduct(EditByOwnersOrAdmins):
     def checkAuthenticated(self, user):
         # Commercial admins may help setup commercial projects.
         return (
-            super(EditProduct, self).checkAuthenticated(user)
+            super().checkAuthenticated(user)
             or is_commercial_case(self.obj, user)
             or False)
 
@@ -580,8 +580,7 @@ class ViewTimelineProductSeries(DelegatedAuthorization):
     usedfor = ITimelineProductSeries
 
     def __init__(self, obj):
-        super(ViewTimelineProductSeries, self).__init__(
-            obj, obj.product, 'launchpad.View')
+        super().__init__(obj, obj.product, 'launchpad.View')
 
 
 class ViewProductReleaseFile(AnonymousAuthorization):
@@ -781,7 +780,7 @@ class ModerateSprint(ModerateByRegistryExpertsOrAdmins):
 
     def checkAuthenticated(self, user):
         return (
-            super(ModerateSprint, self).checkAuthenticated(user) or
+            super().checkAuthenticated(user) or
             user.isOwner(self.obj))
 
 
@@ -850,8 +849,7 @@ class ViewProjectMilestone(DelegatedAuthorization):
     usedfor = IProjectGroupMilestone
 
     def __init__(self, obj):
-        super(ViewProjectMilestone, self).__init__(
-            obj, obj.product, 'launchpad.View')
+        super().__init__(obj, obj.product, 'launchpad.View')
 
 
 class EditProjectMilestoneNever(AuthorizationBase):
@@ -868,8 +866,7 @@ class LimitedViewMilestone(DelegatedAuthorization):
     usedfor = IMilestone
 
     def __init__(self, obj):
-        super(LimitedViewMilestone, self).__init__(
-            obj, obj.target, 'launchpad.LimitedView')
+        super().__init__(obj, obj.target, 'launchpad.LimitedView')
 
 
 class ViewMilestone(AuthorizationBase):
@@ -946,7 +943,7 @@ class ModerateTeam(ModerateByRegistryExpertsOrAdmins):
         registry experts, team admins, or the team owners.
         """
         return (
-            super(ModerateTeam, self).checkAuthenticated(user)
+            super().checkAuthenticated(user)
             or can_edit_team(self.obj, user))
 
 
@@ -986,8 +983,7 @@ class AdminByCommercialTeamOrAdminsOrPerson(AdminByCommercialTeamOrAdmins):
 
     def checkAuthenticated(self, user):
         """Users can manage their commericial data and admins can help."""
-        base = super(AdminByCommercialTeamOrAdminsOrPerson, self)
-        return self.obj.id == user.id or base.checkAuthenticated(user)
+        return self.obj.id == user.id or super().checkAuthenticated(user)
 
 
 class EditPersonBySelfOrAdmins(AuthorizationBase):
@@ -1434,7 +1430,7 @@ class EditDistroSeriesDifference(DelegatedAuthorization):
     usedfor = IDistroSeriesDifferenceEdit
 
     def __init__(self, obj):
-        super(EditDistroSeriesDifference, self).__init__(
+        super().__init__(
             obj, obj.derived_series.distribution, 'launchpad.View')
 
     def checkUnauthenticated(self):
@@ -1462,7 +1458,7 @@ class DriveProduct(SeriesDrivers):
     def checkAuthenticated(self, user):
         # Commercial admins may help setup commercial projects.
         return (
-            super(DriveProduct, self).checkAuthenticated(user)
+            super().checkAuthenticated(user)
             or is_commercial_case(self.obj, user)
             or False)
 
@@ -1472,8 +1468,7 @@ class LimitedViewProductSeries(DelegatedAuthorization):
     usedfor = IProductSeriesLimitedView
 
     def __init__(self, obj):
-        super(LimitedViewProductSeries, self).__init__(
-            obj, obj.product, 'launchpad.LimitedView')
+        super().__init__(obj, obj.product, 'launchpad.LimitedView')
 
 
 class ViewProductSeries(AuthorizationBase):
@@ -1524,8 +1519,7 @@ class ViewDistroArchSeriesFilter(DelegatedAuthorization):
     usedfor = IDistroArchSeriesFilter
 
     def __init__(self, obj):
-        super(ViewDistroArchSeriesFilter, self).__init__(
-            obj, obj.distroarchseries, 'launchpad.View')
+        super().__init__(obj, obj.distroarchseries, 'launchpad.View')
 
 
 class EditDistroArchSeriesFilter(DelegatedAuthorization):
@@ -1533,8 +1527,7 @@ class EditDistroArchSeriesFilter(DelegatedAuthorization):
     usedfor = IDistroArchSeriesFilter
 
     def __init__(self, obj):
-        super(EditDistroArchSeriesFilter, self).__init__(
-            obj, obj.distroarchseries, 'launchpad.Moderate')
+        super().__init__(obj, obj.distroarchseries, 'launchpad.Moderate')
 
 
 class ViewAnnouncement(AuthorizationBase):
@@ -1871,8 +1864,7 @@ class ViewProductRelease(DelegatedAuthorization):
     usedfor = IProductRelease
 
     def __init__(self, obj):
-        super(ViewProductRelease, self).__init__(
-            obj, obj.milestone, 'launchpad.View')
+        super().__init__(obj, obj.milestone, 'launchpad.View')
 
 
 class AdminTranslationImportQueueEntry(AuthorizationBase):
@@ -1985,7 +1977,7 @@ class ViewPackageUploadLog(DelegatedAuthorization):
     usedfor = IPackageUploadLog
 
     def __init__(self, obj):
-        super(ViewPackageUploadLog, self).__init__(obj, obj.package_upload)
+        super().__init__(obj, obj.package_upload)
 
 
 class EditPackageUpload(AdminByAdminsTeam):
@@ -2029,7 +2021,7 @@ class ModerateBuilder(EditBuilder):
 
     def checkAuthenticated(self, user):
         return (user.in_registry_experts or
-                super(ModerateBuilder, self).checkAuthenticated(user))
+                super().checkAuthenticated(user))
 
 
 class AdminBuildRecord(AdminByBuilddAdmin):
@@ -2137,8 +2129,7 @@ class ModerateBinaryPackageBuild(ViewBinaryPackageBuild):
         # administer the archive can already achieve the same effect by
         # setting Archive.external_dependencies.)
         return (
-            super(ModerateBinaryPackageBuild, self).checkAuthenticated(
-                user) and
+            super().checkAuthenticated(user) and
             AdminArchive(self.obj.archive).checkAuthenticated(user))
 
     def checkUnauthenticated(self, user):
@@ -2154,7 +2145,7 @@ class ViewTranslationTemplatesBuild(DelegatedAuthorization):
     usedfor = ITranslationTemplatesBuild
 
     def __init__(self, obj):
-        super(ViewTranslationTemplatesBuild, self).__init__(obj, obj.branch)
+        super().__init__(obj, obj.branch)
 
 
 class AdminQuestion(AuthorizationBase):
@@ -2372,7 +2363,7 @@ class ModerateBranch(EditBranch):
     permission = 'launchpad.Moderate'
 
     def checkAuthenticated(self, user):
-        if super(ModerateBranch, self).checkAuthenticated(user):
+        if super().checkAuthenticated(user):
             return True
         branch = self.obj
         if branch.product is not None and user.inTeam(branch.product.owner):
@@ -2447,7 +2438,7 @@ class ModerateGitRepository(EditGitRepository):
     permission = 'launchpad.Moderate'
 
     def checkAuthenticated(self, user):
-        if super(ModerateGitRepository, self).checkAuthenticated(user):
+        if super().checkAuthenticated(user):
             return True
         target = self.obj.target
         if (target is not None and IProduct.providedBy(target) and
@@ -2467,17 +2458,17 @@ class ViewGitRef(DelegatedAuthorization):
     usedfor = IGitRef
 
     def __init__(self, obj):
-        super(ViewGitRef, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
     def checkAuthenticated(self, user):
         if self.obj.repository is not None:
-            return super(ViewGitRef, self).checkAuthenticated(user)
+            return super().checkAuthenticated(user)
         else:
             return True
 
     def checkUnauthenticated(self):
         if self.obj.repository is not None:
-            return super(ViewGitRef, self).checkUnauthenticated()
+            return super().checkUnauthenticated()
         else:
             return True
 
@@ -2488,7 +2479,7 @@ class EditGitRef(DelegatedAuthorization):
     usedfor = IGitRef
 
     def __init__(self, obj):
-        super(EditGitRef, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
 
 class ViewGitRule(DelegatedAuthorization):
@@ -2497,7 +2488,7 @@ class ViewGitRule(DelegatedAuthorization):
     usedfor = IGitRule
 
     def __init__(self, obj):
-        super(ViewGitRule, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
 
 class EditGitRule(DelegatedAuthorization):
@@ -2506,7 +2497,7 @@ class EditGitRule(DelegatedAuthorization):
     usedfor = IGitRule
 
     def __init__(self, obj):
-        super(EditGitRule, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
 
 class ViewGitRuleGrant(DelegatedAuthorization):
@@ -2515,7 +2506,7 @@ class ViewGitRuleGrant(DelegatedAuthorization):
     usedfor = IGitRuleGrant
 
     def __init__(self, obj):
-        super(ViewGitRuleGrant, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
 
 class EditGitRuleGrant(DelegatedAuthorization):
@@ -2524,7 +2515,7 @@ class EditGitRuleGrant(DelegatedAuthorization):
     usedfor = IGitRuleGrant
 
     def __init__(self, obj):
-        super(EditGitRuleGrant, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
 
 class ViewGitActivity(DelegatedAuthorization):
@@ -2533,7 +2524,7 @@ class ViewGitActivity(DelegatedAuthorization):
     usedfor = IGitActivity
 
     def __init__(self, obj):
-        super(ViewGitActivity, self).__init__(obj, obj.repository)
+        super().__init__(obj, obj.repository)
 
 
 class AdminDistroSeriesTranslations(AuthorizationBase):
@@ -2556,8 +2547,7 @@ class AdminDistributionSourcePackageTranslations(DelegatedAuthorization):
     usedfor = IDistributionSourcePackage
 
     def __init__(self, obj):
-        super(AdminDistributionSourcePackageTranslations, self).__init__(
-            obj, obj.distribution)
+        super().__init__(obj, obj.distribution)
 
 
 class AdminProductSeriesTranslations(AuthorizationBase):
@@ -2626,7 +2616,7 @@ class PreviewDiffView(DelegatedAuthorization):
     usedfor = IPreviewDiff
 
     def __init__(self, obj):
-        super(PreviewDiffView, self).__init__(obj, obj.branch_merge_proposal)
+        super().__init__(obj, obj.branch_merge_proposal)
 
 
 class CodeReviewVoteReferenceView(DelegatedAuthorization):
@@ -2634,8 +2624,7 @@ class CodeReviewVoteReferenceView(DelegatedAuthorization):
     usedfor = ICodeReviewVoteReference
 
     def __init__(self, obj):
-        super(CodeReviewVoteReferenceView, self).__init__(
-            obj, obj.branch_merge_proposal)
+        super().__init__(obj, obj.branch_merge_proposal)
 
 
 class CodeReviewVoteReferenceEdit(DelegatedAuthorization):
@@ -2643,8 +2632,7 @@ class CodeReviewVoteReferenceEdit(DelegatedAuthorization):
     usedfor = ICodeReviewVoteReference
 
     def __init__(self, obj):
-        super(CodeReviewVoteReferenceEdit, self).__init__(
-            obj, obj.branch_merge_proposal.target_branch)
+        super().__init__(obj, obj.branch_merge_proposal.target_branch)
 
     def checkAuthenticated(self, user):
         """Only the affected teams may change the review request.
@@ -2658,8 +2646,7 @@ class CodeReviewVoteReferenceEdit(DelegatedAuthorization):
         """
         return (user.inTeam(self.obj.reviewer) or
                 user.inTeam(self.obj.registrant) or
-                super(CodeReviewVoteReferenceEdit, self).checkAuthenticated(
-                    user))
+                super().checkAuthenticated(user))
 
 
 class CodeReviewCommentView(DelegatedAuthorization):
@@ -2667,8 +2654,7 @@ class CodeReviewCommentView(DelegatedAuthorization):
     usedfor = ICodeReviewComment
 
     def __init__(self, obj):
-        super(CodeReviewCommentView, self).__init__(
-            obj, obj.branch_merge_proposal)
+        super().__init__(obj, obj.branch_merge_proposal)
 
 
 class CodeReviewCommentOwner(AuthorizationBase):
@@ -2685,8 +2671,7 @@ class CodeReviewCommentDelete(DelegatedAuthorization):
     usedfor = ICodeReviewCommentDeletion
 
     def __init__(self, obj):
-        super(CodeReviewCommentDelete, self).__init__(
-            obj, obj.branch_merge_proposal)
+        super().__init__(obj, obj.branch_merge_proposal)
 
 
 class BranchMergeProposalEdit(AuthorizationBase):
@@ -2787,7 +2772,7 @@ class SubscriberViewArchive(ViewArchive):
     def checkAuthenticated(self, user):
         if user.person in self.obj._known_subscribers:
             return True
-        if super(SubscriberViewArchive, self).checkAuthenticated(user):
+        if super().checkAuthenticated(user):
             return True
         filter = get_enabled_archive_filter(
             user.person, include_subscribed=True)
@@ -2837,7 +2822,7 @@ class DeleteArchive(EditArchive):
 
     def checkAuthenticated(self, user):
         return (
-            super(DeleteArchive, self).checkAuthenticated(user) or
+            super().checkAuthenticated(user) or
             (not self.obj.is_main and user.in_registry_experts))
 
 
@@ -2926,12 +2911,11 @@ class EditArchiveAuthToken(DelegatedAuthorization):
     usedfor = IArchiveAuthToken
 
     def __init__(self, obj):
-        super(EditArchiveAuthToken, self).__init__(
-            obj, obj.archive, 'launchpad.Append')
+        super().__init__(obj, obj.archive, 'launchpad.Append')
 
     def checkAuthenticated(self, user):
         return (user.in_admin or
-                super(EditArchiveAuthToken, self).checkAuthenticated(user))
+                super().checkAuthenticated(user))
 
 
 class ViewPersonalArchiveSubscription(DelegatedAuthorization):
@@ -2944,14 +2928,12 @@ class ViewPersonalArchiveSubscription(DelegatedAuthorization):
     usedfor = IPersonalArchiveSubscription
 
     def __init__(self, obj):
-        super(ViewPersonalArchiveSubscription, self).__init__(
-            obj, obj.archive, 'launchpad.Append')
+        super().__init__(obj, obj.archive, 'launchpad.Append')
 
     def checkAuthenticated(self, user):
         if user.person == self.obj.subscriber or user.in_admin:
             return True
-        return super(
-            ViewPersonalArchiveSubscription, self).checkAuthenticated(user)
+        return super().checkAuthenticated(user)
 
 
 class ViewArchiveSubscriber(DelegatedAuthorization):
@@ -2964,13 +2946,12 @@ class ViewArchiveSubscriber(DelegatedAuthorization):
     usedfor = IArchiveSubscriber
 
     def __init__(self, obj):
-        super(ViewArchiveSubscriber, self).__init__(
-            obj, obj, 'launchpad.Edit')
+        super().__init__(obj, obj, 'launchpad.Edit')
 
     def checkAuthenticated(self, user):
         return (user.inTeam(self.obj.subscriber) or
                 user.in_commercial_admin or
-                super(ViewArchiveSubscriber, self).checkAuthenticated(user))
+                super().checkAuthenticated(user))
 
 
 class EditArchiveSubscriber(DelegatedAuthorization):
@@ -2982,13 +2963,12 @@ class EditArchiveSubscriber(DelegatedAuthorization):
     usedfor = IArchiveSubscriber
 
     def __init__(self, obj):
-        super(EditArchiveSubscriber, self).__init__(
-            obj, obj.archive, 'launchpad.Append')
+        super().__init__(obj, obj.archive, 'launchpad.Append')
 
     def checkAuthenticated(self, user):
         return (user.in_admin or
                 user.in_commercial_admin or
-                super(EditArchiveSubscriber, self).checkAuthenticated(user))
+                super().checkAuthenticated(user))
 
 
 class AdminArchiveSubscriberSet(AdminByCommercialTeamOrAdmins):
@@ -3045,8 +3025,7 @@ class EditPublishing(DelegatedAuthorization):
     usedfor = IPublishingEdit
 
     def __init__(self, obj):
-        super(EditPublishing, self).__init__(
-            obj, obj.archive, 'launchpad.Append')
+        super().__init__(obj, obj.archive, 'launchpad.Append')
 
 
 class ViewBinaryPackagePublishingHistory(ViewSourcePackagePublishingHistory):
@@ -3131,7 +3110,7 @@ class EditEmailAddress(EditByOwnersOrAdmins):
         # Always allow users to see their own email addresses.
         if self.obj.person == user:
             return True
-        return super(EditEmailAddress, self).checkAuthenticated(user)
+        return super().checkAuthenticated(user)
 
 
 class ViewGPGKey(AnonymousAuthorization):
@@ -3241,8 +3220,7 @@ class EditMessageRevision(DelegatedAuthorization):
     usedfor = IMessageRevision
 
     def __init__(self, obj):
-        super(EditMessageRevision, self).__init__(
-            obj, obj.message, 'launchpad.Edit')
+        super().__init__(obj, obj.message, 'launchpad.Edit')
 
 
 class ViewPublisherConfig(AdminByAdminsTeam):
@@ -3270,7 +3248,7 @@ class ViewLiveFS(DelegatedAuthorization):
     usedfor = ILiveFS
 
     def __init__(self, obj):
-        super(ViewLiveFS, self).__init__(obj, obj.owner, 'launchpad.View')
+        super().__init__(obj, obj.owner, 'launchpad.View')
 
 
 class EditLiveFS(AuthorizationBase):
@@ -3329,7 +3307,7 @@ class EditLiveFSBuild(AdminByBuilddAdmin):
         auth_livefs = EditLiveFS(self.obj.livefs)
         if auth_livefs.checkAuthenticated(user):
             return True
-        return super(EditLiveFSBuild, self).checkAuthenticated(user)
+        return super().checkAuthenticated(user)
 
 
 class AdminLiveFSBuild(AdminByBuilddAdmin):
@@ -3354,8 +3332,7 @@ class ViewWebhookDeliveryJob(DelegatedAuthorization):
     usedfor = IWebhookDeliveryJob
 
     def __init__(self, obj):
-        super(ViewWebhookDeliveryJob, self).__init__(
-            obj, obj.webhook, 'launchpad.View')
+        super().__init__(obj, obj.webhook, 'launchpad.View')
 
 
 class ViewSnap(AuthorizationBase):
@@ -3434,8 +3411,7 @@ class ViewSnapBuildRequest(DelegatedAuthorization):
     usedfor = ISnapBuildRequest
 
     def __init__(self, obj):
-        super(ViewSnapBuildRequest, self).__init__(
-            obj, obj.snap, 'launchpad.View')
+        super().__init__(obj, obj.snap, 'launchpad.View')
 
 
 class ViewSnapBuild(DelegatedAuthorization):
@@ -3461,7 +3437,7 @@ class EditSnapBuild(AdminByBuilddAdmin):
         auth_snap = EditSnap(self.obj.snap)
         if auth_snap.checkAuthenticated(user):
             return True
-        return super(EditSnapBuild, self).checkAuthenticated(user)
+        return super().checkAuthenticated(user)
 
 
 class AdminSnapBuild(AdminByBuilddAdmin):
@@ -3515,7 +3491,7 @@ class EditOCIProjectSeries(DelegatedAuthorization):
     usedfor = IOCIProjectSeries
 
     def __init__(self, obj):
-        super(EditOCIProjectSeries, self).__init__(obj, obj.oci_project)
+        super().__init__(obj, obj.oci_project)
 
 
 class ViewOCIRecipeBuildRequest(DelegatedAuthorization):
@@ -3523,8 +3499,7 @@ class ViewOCIRecipeBuildRequest(DelegatedAuthorization):
     usedfor = IOCIRecipeBuildRequest
 
     def __init__(self, obj):
-        super(ViewOCIRecipeBuildRequest, self).__init__(
-            obj, obj.recipe, 'launchpad.View')
+        super().__init__(obj, obj.recipe, 'launchpad.View')
 
 
 class ViewOCIRecipe(AnonymousAuthorization):
@@ -3621,7 +3596,7 @@ class EditOCIRecipeBuild(AdminByBuilddAdmin):
         auth_recipe = EditOCIRecipe(self.obj.recipe)
         if auth_recipe.checkAuthenticated(user):
             return True
-        return super(EditOCIRecipeBuild, self).checkAuthenticated(user)
+        return super().checkAuthenticated(user)
 
 
 class AdminOCIRecipeBuild(AdminByBuilddAdmin):
@@ -3700,8 +3675,7 @@ class ViewCharmRecipeBuildRequest(DelegatedAuthorization):
     usedfor = ICharmRecipeBuildRequest
 
     def __init__(self, obj):
-        super(ViewCharmRecipeBuildRequest, self).__init__(
-            obj, obj.recipe, 'launchpad.View')
+        super().__init__(obj, obj.recipe, 'launchpad.View')
 
 
 class ViewCharmRecipeBuild(DelegatedAuthorization):
@@ -3726,7 +3700,7 @@ class EditCharmRecipeBuild(AdminByBuilddAdmin):
         auth_recipe = EditCharmRecipe(self.obj.recipe)
         if auth_recipe.checkAuthenticated(user):
             return True
-        return super(EditCharmRecipeBuild, self).checkAuthenticated(user)
+        return super().checkAuthenticated(user)
 
 
 class AdminCharmRecipeBuild(AdminByBuilddAdmin):
diff --git a/lib/lp/systemhomes.py b/lib/lp/systemhomes.py
index f9d0fd9..9df2372 100644
--- a/lib/lp/systemhomes.py
+++ b/lib/lp/systemhomes.py
@@ -315,7 +315,7 @@ class WebServiceApplication(ServiceRootResource):
         if self.__class__.cached_wadl is None:
             # The cache has been disabled for testing
             # purposes. Generate the WADL.
-            return super(WebServiceApplication, self).toWADL()
+            return super().toWADL()
         if  version not in self.__class__.cached_wadl:
             # It's not cached. Look for it on disk.
             _wadl_filename = self.cachedWADLPath(
@@ -327,9 +327,9 @@ class WebServiceApplication(ServiceRootResource):
                     wadl = _wadl_fd.read()
                 finally:
                     _wadl_fd.close()
-            except IOError:
+            except OSError:
                 # It's not on disk; generate it.
-                wadl = super(WebServiceApplication, self).toWADL()
+                wadl = super().toWADL()
             del _wadl_fd
             self.__class__.cached_wadl[version] = wadl
         return self.__class__.cached_wadl[version]
diff --git a/lib/lp/xmlrpc/application.py b/lib/lp/xmlrpc/application.py
index 1b23765..d7b5edb 100644
--- a/lib/lp/xmlrpc/application.py
+++ b/lib/lp/xmlrpc/application.py
@@ -109,7 +109,7 @@ class SelfTest(LaunchpadXMLRPCView):
 
     def concatenate(self, string1, string2):
         """Return the concatenation of the two given strings."""
-        return u'%s %s' % (string1, string2)
+        return '%s %s' % (string1, string2)
 
     def hello(self):
         """Return a greeting to the logged in user."""
diff --git a/lib/lp/xmlrpc/tests/test_xmlrpc_selftest.py b/lib/lp/xmlrpc/tests/test_xmlrpc_selftest.py
index 9f0d528..d4fa40f 100644
--- a/lib/lp/xmlrpc/tests/test_xmlrpc_selftest.py
+++ b/lib/lp/xmlrpc/tests/test_xmlrpc_selftest.py
@@ -42,7 +42,7 @@ class TestXMLRPCSelfTest(TestCaseWithFactory):
         """
         selftestview = SelfTest('somecontext', 'somerequest')
         self.assertTrue(verifyObject(ISelfTest, selftestview))
-        self.assertEqual(u'foo bar', selftestview.concatenate('foo', 'bar'))
+        self.assertEqual('foo bar', selftestview.concatenate('foo', 'bar'))
         fault = selftestview.make_fault()
         self.assertEqual("<Fault 666: 'Yoghurt and spanners.'>", str(fault))
 
diff --git a/scripts/generate-access-token.py b/scripts/generate-access-token.py
index 961d715..e494888 100755
--- a/scripts/generate-access-token.py
+++ b/scripts/generate-access-token.py
@@ -47,7 +47,7 @@ class AccessTokenGenerator(LaunchpadScript):
         username = self.args[0]
 
         key = six.ensure_text(self.options.consumer_name)
-        consumer = getUtility(IOAuthConsumerSet).new(key, u'')
+        consumer = getUtility(IOAuthConsumerSet).new(key, '')
         request_token, _ = consumer.newRequestToken()
 
         # review by username
diff --git a/scripts/gina.py b/scripts/gina.py
index b679bf8..e8fb3ed 100755
--- a/scripts/gina.py
+++ b/scripts/gina.py
@@ -26,7 +26,7 @@ from lp.soyuz.scripts.gina.runner import run_gina
 class Gina(LaunchpadCronScript):
 
     def __init__(self):
-        super(Gina, self).__init__(name='gina', dbuser=config.gina.dbuser)
+        super().__init__(name='gina', dbuser=config.gina.dbuser)
 
     @property
     def usage(self):
diff --git a/scripts/mlist-import.py b/scripts/mlist-import.py
index b7bf8b7..b418b5c 100755
--- a/scripts/mlist-import.py
+++ b/scripts/mlist-import.py
@@ -40,7 +40,7 @@ class MailingListImport(LaunchpadScript):
 
     def __init__(self, name, dbuser=None):
         self.usage = textwrap.dedent(self.__doc__)
-        super(MailingListImport, self).__init__(name, dbuser)
+        super().__init__(name, dbuser)
 
     def add_my_options(self):
         """See `LaunchpadScript`."""
diff --git a/scripts/update-stacked-on.py b/scripts/update-stacked-on.py
index 7b6bb64..d8351d6 100755
--- a/scripts/update-stacked-on.py
+++ b/scripts/update-stacked-on.py
@@ -56,7 +56,7 @@ class UpdateStackedBranches(LaunchpadScript):
     """Update stacked branches so their stacked_on_location matches the db."""
 
     def __init__(self):
-        super(UpdateStackedBranches, self).__init__('update-stacked-on')
+        super().__init__('update-stacked-on')
 
     def add_my_options(self):
         self.parser.add_option(
diff --git a/scripts/upload2librarian.py b/scripts/upload2librarian.py
index f211095..4c89bad 100755
--- a/scripts/upload2librarian.py
+++ b/scripts/upload2librarian.py
@@ -53,7 +53,7 @@ class LibrarianUploader(LaunchpadScript):
         """
         try:
             file = open(filepath)
-        except IOError:
+        except OSError:
             raise LaunchpadScriptFailure('Could not open: %s' % filepath)
 
         flen = os.stat(filepath).st_size
diff --git a/setup.py b/setup.py
index ee010f0..88f502c 100644
--- a/setup.py
+++ b/setup.py
@@ -51,8 +51,7 @@ class LPScriptWriter(ScriptWriter):
                 "module_name": ep.module_name,
                 })
             args = cls._get_script_args("console", name, header, script_text)
-            for res in args:
-                yield res
+            yield from args
 
 
 class lp_develop(develop):
diff --git a/test_on_merge.py b/test_on_merge.py
index a86ad0e..d35a146 100755
--- a/test_on_merge.py
+++ b/test_on_merge.py
@@ -170,7 +170,29 @@ def run_test_process():
     # Popen.communicate() with large data sets.
     open_readers = {xvfb_proc.stdout}
     while open_readers:
+<<<<<<< test_on_merge.py
         rlist, wlist, xlist = select.select(open_readers, [], [], TIMEOUT)
+=======
+        # select() blocks for a long time and can easily fail with EINTR
+        # <https://bugs.launchpad.net/launchpad/+bug/615740>.  Really we
+        # should have EINTR protection across the whole script (other syscalls
+        # might be interrupted) but this is the longest and most likely to
+        # hit, and doing it perfectly in python has proved to be quite hard in
+        # bzr. -- mbp 20100924
+        while True:
+            try:
+                rlist, wlist, xlist = select.select(
+                    open_readers, [], [], TIMEOUT)
+                break
+            except OSError as e:
+                # nb: select.error doesn't expose a named 'errno' attribute,
+                # at least in python 2.6.5; see
+                # <http://mail.python.org/pipermail/python-dev/2000-October/009671.html>
+                if e.args[0] == errno.EINTR:
+                    continue
+                else:
+                    raise
+>>>>>>> test_on_merge.py
 
         if len(rlist) == 0:
             # The select() statement timed out!
diff --git a/utilities/generate-external-bug-status-docs b/utilities/generate-external-bug-status-docs
index 63a98b6..94ad229 100755
--- a/utilities/generate-external-bug-status-docs
+++ b/utilities/generate-external-bug-status-docs
@@ -26,8 +26,6 @@ from itertools import chain
 from optparse import OptionParser
 import sys
 
-import six
-
 from lp.bugs.externalbugtracker import BUG_TRACKER_CLASSES
 
 
@@ -87,7 +85,7 @@ def generate_table(typ, cls):
 
 def generate_documentable_classes():
     """Yield each class that has a mapping table defined."""
-    for typ, cls in six.iteritems(BUG_TRACKER_CLASSES):
+    for typ, cls in BUG_TRACKER_CLASSES.items():
         if getattr(cls, '_status_lookup', None) is not None:
             yield typ, cls
 
diff --git a/utilities/list-pages b/utilities/list-pages
index 2f584ab..3dd9314 100755
--- a/utilities/list-pages
+++ b/utilities/list-pages
@@ -47,7 +47,6 @@ import _pythonpath  # noqa: F401
 from inspect import getmro
 import os
 
-import six
 from zope.app.wsgi.testlayer import BrowserLayer
 from zope.browserpage.simpleviewclass import simple
 from zope.component import (
@@ -177,7 +176,7 @@ def format_page_adapter(a):
 _BLACKLIST = [
     '__conform__',
     ]
-class Whatever(object):
+class Whatever:
 
     def __init__(self, name, interface=None):
         self._name = name
@@ -196,7 +195,7 @@ class Whatever(object):
 
     def __call__(self, *args, **kwargs):
         args = map(repr, args)
-        args.extend('%s=%r' % (k, v) for k, v in six.iteritems(kwargs))
+        args.extend('%s=%r' % (k, v) for k, v in kwargs.items())
         # If we're being called with no args, assume this is part of crazy
         # TALES stuff:
         #   webapp/metazcml.py(365)path()
@@ -224,7 +223,7 @@ class Whatever(object):
 
 @implementer(ICanonicalUrlData)
 @adapter(object)
-class DefaultCanonicalUrlData(object):
+class DefaultCanonicalUrlData:
     def __init__(self, name):
         self.path = '[[%s]]' % (name,)
         self.rootsite = None
diff --git a/utilities/make-lp-user b/utilities/make-lp-user
index ee792d1..6278075 100755
--- a/utilities/make-lp-user
+++ b/utilities/make-lp-user
@@ -103,12 +103,12 @@ def add_ssh_public_keys(person):
     key_set = getUtility(ISSHKeySet)
     for filename in ('id_rsa.pub', 'id_dsa.pub'):
         try:
-            public_key_file = open(os.path.join(ssh_dir, filename), 'r')
+            public_key_file = open(os.path.join(ssh_dir, filename))
             try:
                 public_key = public_key_file.read()
             finally:
                 public_key_file.close()
-        except (OSError, IOError):
+        except OSError:
             continue
         key_set.new(person, public_key)
         print('Registered SSH key: %s' % (filename,))
diff --git a/utilities/massage-bug-import-xml b/utilities/massage-bug-import-xml
index 997e3dd..7e43831 100755
--- a/utilities/massage-bug-import-xml
+++ b/utilities/massage-bug-import-xml
@@ -14,7 +14,7 @@ NS = "https://launchpad.net/xmlns/2006/bugs";
 def norm_text(elem):
     if elem is not None:
         if elem.text is None:
-            elem.text = u""
+            elem.text = ""
         else:
             elem.text = elem.text.strip()
 
@@ -26,7 +26,7 @@ def truncate(text, message=None):
             message = "[Truncated]"
         else:
             message = "[Truncated; %s]" % message
-        return u"%s...\n\n%s" % (
+        return "%s...\n\n%s" % (
             "\n".join(lines[:30]).strip(), message)
     else:
         return text
@@ -97,7 +97,7 @@ def massage(root, project_name, fix_nickname, tag_nickname):
 
         # Change the nickname.
         if nickname.text is None or fix_nickname:
-            nickname.text = u"%s-%s" % (project_name, bug.get('id'))
+            nickname.text = "%s-%s" % (project_name, bug.get('id'))
 
         # Resolve duplicateof, if it exists.
         if bug.get("id") in duplicates:
@@ -117,11 +117,11 @@ def massage(root, project_name, fix_nickname, tag_nickname):
             if first_comment_text is None:
                 problem_detail("No comments!")
                 problem_resolution("Setting description to '-'.")
-                description.text = u'-'
+                description.text = '-'
             elif len(first_comment_text.text) == 0:
                 problem_detail("First comment has no text!")
                 problem_resolution("Setting description to '-'.")
-                description.text = u'-'
+                description.text = '-'
             else:
                 problem_detail("First comment has text.")
                 problem_resolution("Removing description.")
@@ -159,7 +159,7 @@ def massage(root, project_name, fix_nickname, tag_nickname):
                 problem(
                     "Bug %s's first comment has no text." % bug.get('id'))
                 problem_resolution("Setting comment text to '-'.")
-                first_comment_text.text = u'-'
+                first_comment_text.text = '-'
                 problem_resolved()
             elif len(first_comment_text.text) > 50000:
                 problem(
@@ -170,12 +170,12 @@ def massage(root, project_name, fix_nickname, tag_nickname):
                 attachment = etree.SubElement(
                     first_comment, '{%s}attachment' % NS)
                 etree.SubElement(attachment, '{%s}filename' % NS).text = (
-                    u"%s-bug-%s-full-description.txt" % (
+                    "%s-bug-%s-full-description.txt" % (
                         project_name, bug.get('id')))
                 etree.SubElement(attachment, '{%s}title' % NS).text = (
-                    u"Full description (text/plain, utf-8)")
+                    "Full description (text/plain, utf-8)")
                 etree.SubElement(attachment, '{%s}mimetype' % NS).text = (
-                    u"text/plain")
+                    "text/plain")
                 etree.SubElement(attachment, '{%s}contents' % NS).text = (
                     standard_b64encode(
                         first_comment_text.text.encode('utf-8')
diff --git a/utilities/pglogwatch.py b/utilities/pglogwatch.py
index 52eee17..8d61ed1 100755
--- a/utilities/pglogwatch.py
+++ b/utilities/pglogwatch.py
@@ -38,7 +38,7 @@ def generate_loglines(logfile):
         raise RuntimeError("tail returned %d" % cmd.returncode)
 
 
-class Process(object):
+class Process:
     statement = None
     duration = None
     connection = None
@@ -48,7 +48,7 @@ class Process(object):
         self.pid = pid
 
 
-class Watcher(object):
+class Watcher:
     _line_re = re.compile(r"""
         ^\d{4}-\d\d-\d\d \s \d\d:\d\d:\d\d \s
         \[(?P<pid>\d+)\] \s (?P<type>LOG|ERROR|DETAIL): \s+ (?P<rest>.*)$
diff --git a/utilities/soyuz-sampledata-setup.py b/utilities/soyuz-sampledata-setup.py
index b8cb28e..ba10e40 100755
--- a/utilities/soyuz-sampledata-setup.py
+++ b/utilities/soyuz-sampledata-setup.py
@@ -322,7 +322,7 @@ def sign_code_of_conduct(person, log):
         fake_gpg_key = LaunchpadObjectFactory().makeGPGKey(person)
         Store.of(person).add(SignedCodeOfConduct(
             owner=person, signing_key_fingerprint=fake_gpg_key.fingerprint,
-            signedcode=u"Normally a signed CoC would go here.", active=True))
+            signedcode="Normally a signed CoC would go here.", active=True))
 
 
 def create_ppa_user(username, options, approver, log):