← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:http-client into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:http-client into launchpad:master.

Commit message:
Import http.client directly

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/411239
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:http-client into launchpad:master.
diff --git a/lib/lp/answers/errors.py b/lib/lp/answers/errors.py
index 9f53c38..3a40470 100644
--- a/lib/lp/answers/errors.py
+++ b/lib/lp/answers/errors.py
@@ -11,11 +11,12 @@ __all__ = [
     'QuestionTargetError',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class AddAnswerContactError(ValueError):
     """The person cannot be an answer contact.
 
@@ -24,12 +25,12 @@ class AddAnswerContactError(ValueError):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class FAQTargetError(ValueError):
     """The target must be an `IFAQTarget`."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidQuestionStateError(ValueError):
     """Error raised when the question is in an invalid state.
 
@@ -38,21 +39,21 @@ class InvalidQuestionStateError(ValueError):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NotAnswerContactError(ValueError):
     """The person must be an answer contact."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NotMessageOwnerError(ValueError):
     """The person must be the message owner."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NotQuestionOwnerError(ValueError):
     """The person must be the question owner."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class QuestionTargetError(ValueError):
     """The target must be an `IQueastionTarget`."""
diff --git a/lib/lp/answers/interfaces/faq.py b/lib/lp/answers/interfaces/faq.py
index 2aee883..f51a0ab 100644
--- a/lib/lp/answers/interfaces/faq.py
+++ b/lib/lp/answers/interfaces/faq.py
@@ -9,6 +9,8 @@ __all__ = [
     'IFAQSet',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     error_status,
     export_destructor_operation,
@@ -17,7 +19,6 @@ from lazr.restful.declarations import (
     operation_for_version,
     )
 from lazr.restful.fields import Reference
-from six.moves import http_client
 from zope.interface import Attribute
 from zope.schema import (
     Datetime,
@@ -36,7 +37,7 @@ from lp.services.fields import (
     )
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteFAQ(Exception):
     """The FAQ cannnot be deleted."""
 
diff --git a/lib/lp/app/errors.py b/lib/lp/app/errors.py
index cae54f4..9c16fa0 100644
--- a/lib/lp/app/errors.py
+++ b/lib/lp/app/errors.py
@@ -17,8 +17,9 @@ __all__ = [
     'UserCannotUnsubscribePerson',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.security.interfaces import (
     ForbiddenAttribute,
     Unauthorized,
@@ -33,12 +34,12 @@ class TeamAccountNotClosable(Exception):
     """We do not close team accounts."""
 
 
-@error_status(http_client.NOT_FOUND)
+@error_status(http.client.NOT_FOUND)
 class NotFoundError(KeyError):
     """Launchpad object not found."""
 
 
-@error_status(http_client.GONE)
+@error_status(http.client.GONE)
 class GoneError(KeyError):
     """Launchpad object is gone."""
 
@@ -76,25 +77,25 @@ class POSTToNonCanonicalURL(UnexpectedFormData):
     """
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotUnsubscribePerson(Unauthorized):
     """User does not have permission to unsubscribe person or team."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class SubscriptionPrivacyViolation(Exception):
     """The subscription would violate privacy policies."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class ServiceUsageForbidden(Exception):
     """The specified ServiceUsage is not allowed."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class IncompatibleArguments(Exception):
     """Raised when incompatible arguments are passed to a method."""
 
 
 # Slam a 401 response code onto all ForbiddenAttribute errors.
-error_status(http_client.UNAUTHORIZED)(ForbiddenAttribute)
+error_status(http.client.UNAUTHORIZED)(ForbiddenAttribute)
diff --git a/lib/lp/app/tests/test_errors.py b/lib/lp/app/tests/test_errors.py
index a10eeb1..69fdbea 100644
--- a/lib/lp/app/tests/test_errors.py
+++ b/lib/lp/app/tests/test_errors.py
@@ -1,7 +1,7 @@
 # Copyright 2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-from six.moves.http_client import (
+from http.client import (
     BAD_REQUEST,
     UNAUTHORIZED,
     )
diff --git a/lib/lp/blueprints/errors.py b/lib/lp/blueprints/errors.py
index 478cf9d..6b0a4d8 100644
--- a/lib/lp/blueprints/errors.py
+++ b/lib/lp/blueprints/errors.py
@@ -7,11 +7,12 @@ __all__ = [
     'TargetAlreadyHasSpecification',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class TargetAlreadyHasSpecification(Exception):
     """The ISpecificationTarget already has a specification of that name."""
 
diff --git a/lib/lp/blueprints/interfaces/specification.py b/lib/lp/blueprints/interfaces/specification.py
index a2d0308..739ece3 100644
--- a/lib/lp/blueprints/interfaces/specification.py
+++ b/lib/lp/blueprints/interfaces/specification.py
@@ -12,6 +12,8 @@ __all__ = [
     'ISpecificationView',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     call_with,
     collection_default_content,
@@ -33,7 +35,6 @@ from lazr.restful.fields import (
     ReferenceChoice,
     )
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -91,7 +92,7 @@ from lp.services.webapp import canonical_url
 from lp.services.webapp.escaping import structured
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class GoalProposeError(Exception):
     """Invalid series goal for this specification."""
 
diff --git a/lib/lp/bugs/browser/bugtarget.py b/lib/lp/bugs/browser/bugtarget.py
index 4a2e1d4..a8bfe2e 100644
--- a/lib/lp/bugs/browser/bugtarget.py
+++ b/lib/lp/bugs/browser/bugtarget.py
@@ -19,6 +19,7 @@ __all__ = [
 
 from datetime import datetime
 from functools import partial
+import http.client
 from io import BytesIO
 
 from lazr.restful.interface import copy_field
@@ -26,7 +27,6 @@ from lazr.restful.interfaces import IJSONRequestCache
 from pytz import timezone
 from simplejson import dumps
 import six
-from six.moves import http_client
 from six.moves.urllib.parse import (
     quote,
     urlencode,
@@ -897,7 +897,7 @@ class FileBugAdvancedView(LaunchpadView):
         filebug_url = canonical_url(
             self.context, rootsite='bugs', view_name='+filebug')
         self.request.response.redirect(
-            filebug_url, status=http_client.MOVED_PERMANENTLY)
+            filebug_url, status=http.client.MOVED_PERMANENTLY)
 
 
 class IDistroBugAddForm(IBugAddForm):
diff --git a/lib/lp/bugs/errors.py b/lib/lp/bugs/errors.py
index 06dd12e..03489b6 100644
--- a/lib/lp/bugs/errors.py
+++ b/lib/lp/bugs/errors.py
@@ -8,17 +8,18 @@ __all__ = [
     'InvalidSearchParameters',
 ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 
 from lp.app.validators import LaunchpadValidationError
 
 
-@error_status(http_client.EXPECTATION_FAILED)
+@error_status(http.client.EXPECTATION_FAILED)
 class InvalidDuplicateValue(LaunchpadValidationError):
     """A bug cannot be set as the duplicate of another."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidSearchParameters(ValueError):
     """Invalid search parameters were passed to searchTasks."""
diff --git a/lib/lp/bugs/externalbugtracker/bugzilla.py b/lib/lp/bugs/externalbugtracker/bugzilla.py
index acfa428..5269ebc 100644
--- a/lib/lp/bugs/externalbugtracker/bugzilla.py
+++ b/lib/lp/bugs/externalbugtracker/bugzilla.py
@@ -11,6 +11,7 @@ __all__ = [
     ]
 
 from email.utils import parseaddr
+from http.client import BadStatusLine
 import re
 import xml.parsers.expat
 
@@ -19,7 +20,6 @@ import pytz
 import requests
 import six
 from six.moves import xmlrpc_client
-from six.moves.http_client import BadStatusLine
 from zope.component import getUtility
 from zope.interface import (
     alsoProvides,
diff --git a/lib/lp/bugs/externalbugtracker/github.py b/lib/lp/bugs/externalbugtracker/github.py
index 0756a5b..d5b6f25 100644
--- a/lib/lp/bugs/externalbugtracker/github.py
+++ b/lib/lp/bugs/externalbugtracker/github.py
@@ -11,11 +11,11 @@ __all__ = [
     ]
 
 from contextlib import contextmanager
+import http.client
 import time
 
 import pytz
 import requests
-from six.moves import http_client
 from six.moves.urllib.parse import (
     urlencode,
     urlunsplit,
@@ -258,7 +258,7 @@ class GitHub(ExternalBugTracker):
             except BugTrackerConnectError as e:
                 if (e.error.response is not None and
                     e.error.response.status_code ==
-                        http_client.NOT_MODIFIED):
+                        http.client.NOT_MODIFIED):
                     return
                 else:
                     raise
diff --git a/lib/lp/bugs/externalbugtracker/gitlab.py b/lib/lp/bugs/externalbugtracker/gitlab.py
index dc5e104..d62552b 100644
--- a/lib/lp/bugs/externalbugtracker/gitlab.py
+++ b/lib/lp/bugs/externalbugtracker/gitlab.py
@@ -8,8 +8,9 @@ __all__ = [
     'GitLab',
     ]
 
+import http.client
+
 import pytz
-from six.moves import http_client
 from six.moves.urllib.parse import (
     quote,
     quote_plus,
@@ -159,7 +160,7 @@ class GitLab(ExternalBugTracker):
             except BugTrackerConnectError as e:
                 if (e.error.response is not None and
                     e.error.response.status_code ==
-                        http_client.NOT_MODIFIED):
+                        http.client.NOT_MODIFIED):
                     return
                 else:
                     raise
diff --git a/lib/lp/bugs/interfaces/bugnomination.py b/lib/lp/bugs/interfaces/bugnomination.py
index 8937aa0..34ce08e 100644
--- a/lib/lp/bugs/interfaces/bugnomination.py
+++ b/lib/lp/bugs/interfaces/bugnomination.py
@@ -12,6 +12,8 @@ __all__ = [
     'BugNominationStatus',
     'NominationSeriesObsoleteError']
 
+import http.client
+
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -29,7 +31,6 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -52,17 +53,17 @@ from lp.registry.interfaces.role import IHasOwner
 from lp.services.fields import PublicPersonChoice
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NominationError(Exception):
     """The bug cannot be nominated for this release."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NominationSeriesObsoleteError(Exception):
     """A bug cannot be nominated for an obsolete series."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BugNominationStatusError(Exception):
     """A error occurred while trying to set a bug nomination status."""
 
diff --git a/lib/lp/bugs/interfaces/bugtask.py b/lib/lp/bugs/interfaces/bugtask.py
index 4011106..141034f 100644
--- a/lib/lp/bugs/interfaces/bugtask.py
+++ b/lib/lp/bugs/interfaces/bugtask.py
@@ -32,6 +32,8 @@ __all__ = [
     'valid_remote_bug_url',
     ]
 
+import http.client
+
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -58,7 +60,6 @@ from lazr.restful.fields import (
     ReferenceChoice,
     )
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -320,7 +321,7 @@ BUG_SUPERVISOR_BUGTASK_STATUSES = (
     BugTaskStatus.TRIAGED)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteBugtask(Exception):
     """The bugtask cannot be deleted.
 
@@ -329,7 +330,7 @@ class CannotDeleteBugtask(Exception):
     """
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotEditBugTaskStatus(Unauthorized):
     """User not permitted to change status.
 
@@ -338,7 +339,7 @@ class UserCannotEditBugTaskStatus(Unauthorized):
     """
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotEditBugTaskImportance(Unauthorized):
     """User not permitted to change importance.
 
@@ -347,7 +348,7 @@ class UserCannotEditBugTaskImportance(Unauthorized):
     """
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotEditBugTaskMilestone(Unauthorized):
     """User not permitted to change milestone.
 
@@ -356,7 +357,7 @@ class UserCannotEditBugTaskMilestone(Unauthorized):
     """
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotEditBugTaskAssignee(Unauthorized):
     """User not permitted to change bugtask assignees.
 
@@ -365,7 +366,7 @@ class UserCannotEditBugTaskAssignee(Unauthorized):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class IllegalTarget(Exception):
     """Exception raised when trying to set an illegal bug task target."""
 
diff --git a/lib/lp/bugs/interfaces/bugtasksearch.py b/lib/lp/bugs/interfaces/bugtasksearch.py
index 6ec6ce2..ce3970a 100644
--- a/lib/lp/bugs/interfaces/bugtasksearch.py
+++ b/lib/lp/bugs/interfaces/bugtasksearch.py
@@ -19,6 +19,7 @@ __all__ = [
     ]
 
 import collections
+import http.client
 
 from lazr.enum import (
     EnumeratedType,
@@ -26,7 +27,6 @@ from lazr.enum import (
     )
 from lazr.restful.declarations import error_status
 from lazr.restful.fields import ReferenceChoice
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Bool,
@@ -57,7 +57,7 @@ from lp.services.searchbuilder import (
 from lp.soyuz.interfaces.component import IComponent
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class IllegalRelatedBugTasksParams(Exception):
     """Exception raised when trying to overwrite all relevant parameters
     in a search for related bug tasks"""
diff --git a/lib/lp/bugs/model/bugsubscriptionfilter.py b/lib/lp/bugs/model/bugsubscriptionfilter.py
index 727830e..c3568d6 100644
--- a/lib/lp/bugs/model/bugsubscriptionfilter.py
+++ b/lib/lp/bugs/model/bugsubscriptionfilter.py
@@ -10,11 +10,11 @@ __all__ = [
     'BugSubscriptionFilterTag',
     ]
 
+import http.client
 from itertools import chain
 
 from lazr.restful.declarations import error_status
 import pytz
-from six.moves import http_client
 from storm.expr import (
     Exists,
     Not,
@@ -50,7 +50,7 @@ from lp.services.database.sqlbase import convert_storm_clause_to_string
 from lp.services.database.stormbase import StormBase
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class MuteNotAllowed(Exception):
     """Raised when someone tries to mute a filter that can't be muted."""
 
diff --git a/lib/lp/bugs/tests/test_errors.py b/lib/lp/bugs/tests/test_errors.py
index aea8a32..b9e43ec 100644
--- a/lib/lp/bugs/tests/test_errors.py
+++ b/lib/lp/bugs/tests/test_errors.py
@@ -3,7 +3,7 @@
 
 """Tests for bugs errors."""
 
-from six.moves.http_client import EXPECTATION_FAILED
+from http.client import EXPECTATION_FAILED
 
 from lp.bugs.errors import InvalidDuplicateValue
 from lp.testing import TestCase
diff --git a/lib/lp/charms/interfaces/charmrecipe.py b/lib/lp/charms/interfaces/charmrecipe.py
index b48495e..5f95f7c 100644
--- a/lib/lp/charms/interfaces/charmrecipe.py
+++ b/lib/lp/charms/interfaces/charmrecipe.py
@@ -30,6 +30,8 @@ __all__ = [
     "NoSuchCharmRecipe",
     ]
 
+import http.client
+
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -57,7 +59,6 @@ from lazr.restful.fields import (
     ReferenceChoice,
     )
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -100,7 +101,7 @@ CHARM_RECIPE_BUILD_DISTRIBUTION = "charm.default_build_distribution"
 CHARM_RECIPE_WEBHOOKS_FEATURE_FLAG = "charm.recipe.webhooks.enabled"
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class CharmRecipeFeatureDisabled(Unauthorized):
     """Only certain users can create new charm recipes."""
 
@@ -109,7 +110,7 @@ class CharmRecipeFeatureDisabled(Unauthorized):
             "You do not have permission to create new charm recipes.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class CharmRecipePrivateFeatureDisabled(Unauthorized):
     """Only certain users can create private charm recipes."""
 
@@ -118,7 +119,7 @@ class CharmRecipePrivateFeatureDisabled(Unauthorized):
             "You do not have permission to create private charm recipes.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DuplicateCharmRecipeName(Exception):
     """Raised for charm recipes with duplicate project/owner/name."""
 
@@ -128,7 +129,7 @@ class DuplicateCharmRecipeName(Exception):
             "and name.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class CharmRecipeNotOwner(Unauthorized):
     """The registrant/requester is not the owner or a member of its team."""
 
@@ -138,7 +139,7 @@ class NoSuchCharmRecipe(NameLookupFailed):
     _message_prefix = "No such charm recipe with this owner and project"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoSourceForCharmRecipe(Exception):
     """Charm recipes must have a source (Git branch)."""
 
@@ -147,12 +148,12 @@ class NoSourceForCharmRecipe(Exception):
             "New charm recipes must have a Git branch.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BadCharmRecipeSource(Exception):
     """The elements of the source for a charm recipe are inconsistent."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CharmRecipePrivacyMismatch(Exception):
     """Charm recipe privacy does not match its content."""
 
@@ -166,7 +167,7 @@ class BadCharmRecipeSearchContext(Exception):
     """The context is not valid for a charm recipe search."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotAuthorizeCharmhubUploads(Exception):
     """Cannot authorize uploads of a charm to Charmhub."""
 
@@ -187,7 +188,7 @@ class CannotParseCharmcraftYaml(Exception):
     """Launchpad cannot parse this charm recipe's charmcraft.yaml."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CharmRecipeBuildAlreadyPending(Exception):
     """A build was requested when an identical build was already pending."""
 
@@ -196,7 +197,7 @@ class CharmRecipeBuildAlreadyPending(Exception):
             "An identical build of this charm recipe is already pending.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CharmRecipeBuildDisallowedArchitecture(Exception):
     """A build was requested for a disallowed architecture."""
 
diff --git a/lib/lp/code/errors.py b/lib/lp/code/errors.py
index 9a17370..885662e 100644
--- a/lib/lp/code/errors.py
+++ b/lib/lp/code/errors.py
@@ -66,10 +66,11 @@ __all__ = [
     'WrongBranchMergeProposal',
 ]
 
+import http.client
+
 from breezy.plugins.builder.recipe import RecipeParseError
 from lazr.restful.declarations import error_status
 import six
-from six.moves import http_client
 
 from lp.app.errors import (
     NameLookupFailed,
@@ -78,14 +79,14 @@ from lp.app.errors import (
 
 
 # Annotate the RecipeParseError's with a 400 webservice status.
-error_status(http_client.BAD_REQUEST)(RecipeParseError)
+error_status(http.client.BAD_REQUEST)(RecipeParseError)
 
 
 class BadBranchMergeProposalSearchContext(Exception):
     """The context is not valid for a branch merge proposal search."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BadStateTransition(Exception):
     """The user requested a state transition that is not possible."""
 
@@ -94,7 +95,7 @@ class BranchCreationException(Exception):
     """Base class for branch creation exceptions."""
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class BranchExists(BranchCreationException):
     """Raised when creating a branch that already exists."""
 
@@ -130,7 +131,7 @@ class BranchTargetError(Exception):
     """Raised when there is an error determining a branch target."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteBranch(Exception):
     """The branch cannot be deleted at this time."""
 
@@ -143,7 +144,7 @@ class BranchCreationForbidden(BranchCreationException):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BranchCreatorNotMemberOfOwnerTeam(BranchCreationException):
     """Branch creator is not a member of the owner team.
 
@@ -152,7 +153,7 @@ class BranchCreatorNotMemberOfOwnerTeam(BranchCreationException):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BranchCreatorNotOwner(BranchCreationException):
     """A user cannot create a branch belonging to another user.
 
@@ -232,7 +233,7 @@ class ClaimReviewFailed(Exception):
     """The user cannot claim the pending review."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidBranchMergeProposal(Exception):
     """Raised during the creation of a new branch merge proposal.
 
@@ -240,7 +241,7 @@ class InvalidBranchMergeProposal(Exception):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BranchMergeProposalExists(InvalidBranchMergeProposal):
     """Raised if there is already a matching BranchMergeProposal."""
 
@@ -304,7 +305,7 @@ class StaleLastMirrored(Exception):
             (db_branch.last_mirrored_id, self.info['last_revision_id']))
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class PrivateBranchRecipe(Exception):
 
     def __init__(self, branch):
@@ -314,7 +315,7 @@ class PrivateBranchRecipe(Exception):
         Exception.__init__(self, message)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class PrivateGitRepositoryRecipe(Exception):
 
     def __init__(self, repository):
@@ -386,7 +387,7 @@ class GitRepositoryCreationException(Exception):
     """Base class for Git repository creation exceptions."""
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class GitRepositoryExists(GitRepositoryCreationException):
     """Raised when creating a Git repository that already exists."""
 
@@ -402,7 +403,7 @@ class GitRepositoryExists(GitRepositoryCreationException):
         GitRepositoryCreationException.__init__(self, message)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteGitRepository(Exception):
     """The Git repository cannot be deleted at this time."""
 
@@ -416,7 +417,7 @@ class GitRepositoryCreationForbidden(GitRepositoryCreationException):
 
 
 @six.python_2_unicode_compatible
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class GitRepositoryCreatorNotMemberOfOwnerTeam(GitRepositoryCreationException):
     """Git repository creator is not a member of the owner team.
 
@@ -435,7 +436,7 @@ class GitRepositoryCreatorNotMemberOfOwnerTeam(GitRepositoryCreationException):
 
 
 @six.python_2_unicode_compatible
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class GitRepositoryCreatorNotOwner(GitRepositoryCreationException):
     """A user cannot create a Git repository belonging to another user.
 
@@ -534,7 +535,7 @@ class NoSuchGitReference(NotFoundError):
         return self.message
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class GitDefaultConflict(Exception):
     """Raised when trying to set a Git repository as the default for
     something that already has a default."""
@@ -559,7 +560,7 @@ class GitDefaultConflict(Exception):
         Exception.__init__(self, message)
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotModifyNonHostedGitRepository(Exception):
     """Raised when trying to modify a non-hosted Git repository."""
 
@@ -569,7 +570,7 @@ class CannotModifyNonHostedGitRepository(Exception):
             repository.display_name)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CodeImportNotInReviewedState(Exception):
     """Raised when the user requests an import of a non-automatic import."""
 
@@ -582,12 +583,12 @@ class CodeImportAlreadyRequested(Exception):
         self.requesting_user = requesting_user
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CodeImportAlreadyRunning(Exception):
     """Raised when the user requests an import that is already running."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CodeImportInvalidTargetType(Exception):
     """Raised for code imports with an invalid target for their type."""
 
@@ -597,7 +598,7 @@ class CodeImportInvalidTargetType(Exception):
             (target.__class__.__name__, target_rcs_type))
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class TooNewRecipeFormat(Exception):
     """The format of the recipe supplied was too new."""
 
@@ -607,7 +608,7 @@ class TooNewRecipeFormat(Exception):
         self.newest_supported = newest_supported
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class RecipeBuildException(Exception):
 
     def __init__(self, recipe, distroseries, template):
@@ -635,6 +636,6 @@ class BuildNotAllowedForDistro(RecipeBuildException):
             'A build against this distro is not allowed.')
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DiffNotFound(Exception):
     """A `IPreviewDiff` with the timestamp was not found."""
diff --git a/lib/lp/code/interfaces/branch.py b/lib/lp/code/interfaces/branch.py
index f1c53f5..e6d4e14 100644
--- a/lib/lp/code/interfaces/branch.py
+++ b/lib/lp/code/interfaces/branch.py
@@ -20,6 +20,7 @@ __all__ = [
     'WrongNumberOfReviewTypeArguments',
     ]
 
+import http.client
 import re
 
 from lazr.restful.declarations import (
@@ -49,7 +50,6 @@ from lazr.restful.fields import (
     )
 from lazr.restful.interface import copy_field
 from lazr.uri import URI
-from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -114,7 +114,7 @@ DEFAULT_BRANCH_STATUS_IN_LISTING = (
     BranchLifecycleStatus.MATURE)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class WrongNumberOfReviewTypeArguments(ValueError):
     """Raised in the webservice API if `reviewers` and `review_types`
     do not have equal length.
diff --git a/lib/lp/codehosting/puller/tests/test_errors.py b/lib/lp/codehosting/puller/tests/test_errors.py
index b6a66e3..47676ed 100644
--- a/lib/lp/codehosting/puller/tests/test_errors.py
+++ b/lib/lp/codehosting/puller/tests/test_errors.py
@@ -3,6 +3,7 @@
 
 """Unit tests for the error presentation in worker.py."""
 
+import http.client
 import os
 import socket
 import tempfile
@@ -19,7 +20,6 @@ from breezy.url_policy_open import (
     BranchReferenceForbidden,
     )
 from lazr.uri import InvalidURIError
-from six.moves import http_client
 from six.moves.urllib.error import HTTPError
 
 from lp.code.enums import BranchType
@@ -140,7 +140,7 @@ class TestErrorCatching(TestCase):
         # error message.
         msg = self.getMirrorFailureForException(
             HTTPError(
-                'http://something', http_client.UNAUTHORIZED,
+                'http://something', http.client.UNAUTHORIZED,
                 'Authorization Required', 'some headers',
                 os.fdopen(tempfile.mkstemp()[0])))
         self.assertEqual("Authentication required.", msg)
diff --git a/lib/lp/codehosting/puller/worker.py b/lib/lp/codehosting/puller/worker.py
index 4ed9b9b..fb3c21a 100644
--- a/lib/lp/codehosting/puller/worker.py
+++ b/lib/lp/codehosting/puller/worker.py
@@ -1,6 +1,7 @@
 # Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
+import http.client
 import socket
 import sys
 
@@ -39,7 +40,6 @@ from lazr.uri import (
     URI,
     )
 import six
-from six.moves import http_client
 from six.moves.urllib.error import HTTPError
 
 from lp.code.bzr import (
@@ -392,7 +392,7 @@ class PullerWorker:
         #
         except HTTPError as e:
             msg = str(e)
-            if int(e.code) == http_client.UNAUTHORIZED:
+            if int(e.code) == http.client.UNAUTHORIZED:
                 # Maybe this will be caught in bzrlib one day, and then we'll
                 # be able to get rid of this.
                 # https://launchpad.net/products/bzr/+bug/42383
diff --git a/lib/lp/oci/interfaces/ocipushrule.py b/lib/lp/oci/interfaces/ocipushrule.py
index d235907..5619875 100644
--- a/lib/lp/oci/interfaces/ocipushrule.py
+++ b/lib/lp/oci/interfaces/ocipushrule.py
@@ -9,6 +9,8 @@ __all__ = [
     'OCIPushRuleAlreadyExists',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     error_status,
     export_destructor_operation,
@@ -20,7 +22,6 @@ from lazr.restful.declarations import (
     operation_parameters,
     )
 from lazr.restful.fields import Reference
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Int,
@@ -32,7 +33,7 @@ from lp.oci.interfaces.ocirecipe import IOCIRecipe
 from lp.oci.interfaces.ociregistrycredentials import IOCIRegistryCredentials
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class OCIPushRuleAlreadyExists(Exception):
     """A new OCIPushRuleAlreadyExists was added with the
        same details as an existing one.
diff --git a/lib/lp/oci/interfaces/ocirecipe.py b/lib/lp/oci/interfaces/ocirecipe.py
index 325de85..47fffe7 100644
--- a/lib/lp/oci/interfaces/ocirecipe.py
+++ b/lib/lp/oci/interfaces/ocirecipe.py
@@ -25,6 +25,8 @@ __all__ = [
     'UsingDistributionCredentials',
     ]
 
+import http.client
+
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -42,7 +44,6 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -88,7 +89,7 @@ OCI_RECIPE_BUILD_DISTRIBUTION = 'oci.default_build_distribution'
 OCI_RECIPE_PRIVATE_FEATURE_FLAG = "oci.recipe.allow_private"
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class OCIRecipeFeatureDisabled(Unauthorized):
     """Only certain users can create new OCI recipes."""
 
@@ -97,12 +98,12 @@ class OCIRecipeFeatureDisabled(Unauthorized):
             "You do not have permission to create new OCI recipes.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class OCIRecipeNotOwner(Unauthorized):
     """The registrant/requester is not the owner or a member of its team."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class OCIRecipeBuildAlreadyPending(Exception):
     """A build was requested when an identical build was already pending."""
 
@@ -111,7 +112,7 @@ class OCIRecipeBuildAlreadyPending(Exception):
             "An identical build of this OCI recipe is already pending.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DuplicateOCIRecipeName(Exception):
     """An OCI Recipe already exists with the same name."""
 
@@ -121,7 +122,7 @@ class NoSuchOCIRecipe(NameLookupFailed):
     _message_prefix = "No such OCI recipe exists for this OCI project"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class UsingDistributionCredentials(Exception):
     """The OCI Recipe is in a Distribution that has credentials set."""
 
@@ -130,7 +131,7 @@ class UsingDistributionCredentials(Exception):
             "The OCI recipe is in a distribution that has credentials set.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoSourceForOCIRecipe(Exception):
     """OCI Recipes must have a source and build file."""
 
@@ -139,7 +140,7 @@ class NoSourceForOCIRecipe(Exception):
             "New OCI recipes must have a git branch and build file.")
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotModifyOCIRecipeProcessor(Exception):
     """Tried to enable or disable a restricted processor on an OCI recipe."""
 
@@ -152,7 +153,7 @@ class CannotModifyOCIRecipeProcessor(Exception):
             self._fmt % {'processor': processor.name})
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class OCIRecipePrivacyMismatch(Exception):
     """OCI recipe privacy does not match its content."""
 
@@ -162,7 +163,7 @@ class OCIRecipePrivacyMismatch(Exception):
             "OCI recipe contains private information and cannot be public.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class OCIRecipeBranchHasInvalidFormat(Exception):
     """The branch name for the OCI recipe does not match the correct format."""
 
diff --git a/lib/lp/oci/interfaces/ocirecipebuild.py b/lib/lp/oci/interfaces/ocirecipebuild.py
index 260e622..32aabe0 100644
--- a/lib/lp/oci/interfaces/ocirecipebuild.py
+++ b/lib/lp/oci/interfaces/ocirecipebuild.py
@@ -13,6 +13,8 @@ __all__ = [
     'OCIRecipeBuildSetRegistryUploadStatus',
     ]
 
+import http.client
+
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -29,7 +31,6 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -58,7 +59,7 @@ from lp.services.librarian.interfaces import ILibraryFileAlias
 from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotScheduleRegistryUpload(Exception):
     """This build cannot be uploaded to registries."""
 
diff --git a/lib/lp/oci/interfaces/ociregistrycredentials.py b/lib/lp/oci/interfaces/ociregistrycredentials.py
index 82f768c..16af53e 100644
--- a/lib/lp/oci/interfaces/ociregistrycredentials.py
+++ b/lib/lp/oci/interfaces/ociregistrycredentials.py
@@ -11,8 +11,9 @@ __all__ = [
     'user_can_edit_credentials_for_owner',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Int,
@@ -31,7 +32,7 @@ from lp.services.fields import (
     )
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class OCIRegistryCredentialsAlreadyExist(Exception):
     """A new `OCIRegistryCredentials` was added with the
     same details as an existing one.
@@ -43,7 +44,7 @@ class OCIRegistryCredentialsAlreadyExist(Exception):
             "region.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class OCIRegistryCredentialsNotOwner(Unauthorized):
     """The registrant is not the owner or a member of its team."""
 
diff --git a/lib/lp/registry/errors.py b/lib/lp/registry/errors.py
index 57d6aaa..4e1c52f 100644
--- a/lib/lp/registry/errors.py
+++ b/lib/lp/registry/errors.py
@@ -34,25 +34,26 @@ __all__ = [
     'UserCannotSubscribePerson',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.schema.interfaces import ConstraintNotSatisfied
 from zope.security.interfaces import Unauthorized
 
 from lp.app.errors import NameLookupFailed
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class PrivatePersonLinkageError(ValueError):
     """An attempt was made to link a private person/team to something."""
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class InclusiveTeamLinkageError(ValueError):
     """An attempt was made to link an open team to something."""
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class NameAlreadyTaken(Exception):
     """The name given for a person is already in use by other person."""
 
@@ -61,17 +62,17 @@ class InvalidName(Exception):
     """The name given for a person is not valid."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NotPlaceholderAccount(Exception):
     """A non-placeholder account already exists for that OpenID identifier."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoSuchAccount(Exception):
     """No account exists for the specified openid identifier."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidFilename(Exception):
     """An invalid filename was used as an attachment filename."""
 
@@ -81,7 +82,7 @@ class NoSuchDistroSeries(NameLookupFailed):
     _message_prefix = "No such distribution series"
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotChangeMembershipSilently(Unauthorized):
     """User not permitted to change membership status silently.
 
@@ -90,7 +91,7 @@ class UserCannotChangeMembershipSilently(Unauthorized):
     """
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CommercialSubscribersOnly(Unauthorized):
     """Feature is only available to current commercial subscribers.
 
@@ -113,7 +114,7 @@ class NoSuchOCIProjectName(NameLookupFailed):
     _message_prefix = "No such OCI Project"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotTransitionToCountryMirror(Exception):
     """Root exception for transitions to country mirrors."""
 
@@ -150,7 +151,7 @@ class MirrorNotProbed(CannotTransitionToCountryMirror):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DeleteSubscriptionError(Exception):
     """Delete Subscription Error.
 
@@ -158,12 +159,12 @@ class DeleteSubscriptionError(Exception):
     structural subscription."""
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotSubscribePerson(Exception):
     """User does not have permission to subscribe the person or team."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DistroSeriesDifferenceError(Exception):
     """Raised when package diffs cannot be created for a difference."""
 
@@ -175,7 +176,7 @@ class NotADerivedSeriesError(Exception):
     non-derived series - that is, a distroseries with a null Parent."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class TeamMembershipTransitionError(ValueError):
     """Indicates something has gone wrong with the transtiion.
 
@@ -184,7 +185,7 @@ class TeamMembershipTransitionError(ValueError):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class TeamMembershipPolicyError(ConstraintNotSatisfied):
     """The team cannot have the specified TeamMembershipPolicy.
 
@@ -208,12 +209,12 @@ class TeamMembershipPolicyError(ConstraintNotSatisfied):
         return self.message
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class JoinNotAllowed(Exception):
     """User is not allowed to join a given team."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class PPACreationError(Exception):
     """Raised when there is an issue creating a new PPA."""
 
@@ -222,12 +223,12 @@ class CannotDeleteCommercialSubscription(Exception):
     """Raised when a commercial subscription cannot be deleted."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotChangeInformationType(Exception):
     """The information type cannot be changed."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidMirrorReviewState(Exception):
     """The mirror is in an invalid state in the review workflow."""
 
diff --git a/lib/lp/registry/interfaces/distribution.py b/lib/lp/registry/interfaces/distribution.py
index 3c863b7..03a4d15 100644
--- a/lib/lp/registry/interfaces/distribution.py
+++ b/lib/lp/registry/interfaces/distribution.py
@@ -15,6 +15,8 @@ __all__ = [
     'NoOCIAdminForDistribution',
     ]
 
+import http.client
+
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -39,7 +41,6 @@ from lazr.restful.fields import (
     Reference,
     )
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -115,7 +116,7 @@ from lp.translations.interfaces.hastranslationimports import (
 from lp.translations.interfaces.translationpolicy import ITranslationPolicy
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoOCIAdminForDistribution(Exception):
     """There is no OCI Project Admin for this distribution."""
 
diff --git a/lib/lp/registry/interfaces/distroseries.py b/lib/lp/registry/interfaces/distroseries.py
index 2b56254..8d43db5 100644
--- a/lib/lp/registry/interfaces/distroseries.py
+++ b/lib/lp/registry/interfaces/distroseries.py
@@ -12,6 +12,8 @@ __all__ = [
     'IDistroSeriesSet',
     ]
 
+import http.client
+
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -33,7 +35,6 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
-from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -1041,7 +1042,7 @@ class IDistroSeriesSet(Interface):
         """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DerivationError(Exception):
     """Raised when there is a problem deriving a distroseries."""
     _message_prefix = "Error deriving distro series"
diff --git a/lib/lp/registry/interfaces/ociproject.py b/lib/lp/registry/interfaces/ociproject.py
index 31d08c3..651c987 100644
--- a/lib/lp/registry/interfaces/ociproject.py
+++ b/lib/lp/registry/interfaces/ociproject.py
@@ -12,6 +12,8 @@ __all__ = [
     'OCIProjectRecipeInvalid',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     call_with,
     error_status,
@@ -29,7 +31,6 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -72,12 +73,12 @@ from lp.services.fields import (
 OCI_PROJECT_ALLOW_CREATE = 'oci.project.create.enabled'
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteOCIProject(Exception):
     """The OCIProject cannnot be deleted."""
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class OCIProjectRecipeInvalid(Unauthorized):
     """The given recipe is invalid for this OCI project."""
 
@@ -291,7 +292,7 @@ class IOCIProjectSet(Interface):
         """Preload data for the given list of OCIProject objects."""
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class OCIProjectCreateFeatureDisabled(Unauthorized):
     """Only certain users can create new OCI Projects."""
 
diff --git a/lib/lp/registry/interfaces/person.py b/lib/lp/registry/interfaces/person.py
index 3610054..2b1f3de 100644
--- a/lib/lp/registry/interfaces/person.py
+++ b/lib/lp/registry/interfaces/person.py
@@ -37,6 +37,8 @@ __all__ = [
     'validate_membership_policy',
     ]
 
+import http.client
+
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -68,7 +70,6 @@ from lazr.restful.fields import (
     )
 from lazr.restful.interface import copy_field
 import six
-from six.moves import http_client
 from zope.component import getUtility
 from zope.formlib.form import NoInputData
 from zope.interface import (
@@ -2696,12 +2697,12 @@ class AlreadyConvertedException(Exception):
     """Raised when attempting to claim a team that has been claimed."""
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class ImmutableVisibilityError(Exception):
     """A change in team membership visibility is not allowed."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoAccountError(Exception):
     """The person has no account."""
 
diff --git a/lib/lp/registry/interfaces/poll.py b/lib/lp/registry/interfaces/poll.py
index f73aeb8..9fb73ba 100644
--- a/lib/lp/registry/interfaces/poll.py
+++ b/lib/lp/registry/interfaces/poll.py
@@ -22,6 +22,7 @@ from datetime import (
     datetime,
     timedelta,
     )
+import http.client
 
 from lazr.enum import (
     DBEnumeratedType,
@@ -40,7 +41,6 @@ from lazr.restful.declarations import (
     )
 from lazr.restful.fields import Reference
 import pytz
-from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -128,7 +128,7 @@ class PollStatus:
     ALL = frozenset([OPEN, CLOSED, NOT_YET_OPENED])
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotCreatePoll(Exception):
     pass
 
diff --git a/lib/lp/registry/interfaces/ssh.py b/lib/lp/registry/interfaces/ssh.py
index 5f78968..51d9133 100644
--- a/lib/lp/registry/interfaces/ssh.py
+++ b/lib/lp/registry/interfaces/ssh.py
@@ -11,6 +11,8 @@ __all__ = [
     'SSHKeyType',
     ]
 
+import http.client
+
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -21,7 +23,6 @@ from lazr.restful.declarations import (
     exported_as_webservice_entry,
     )
 import six
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Choice,
@@ -124,7 +125,7 @@ class ISSHKeySet(Interface):
         """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class SSHKeyAdditionError(Exception):
     """Raised when the SSH public key is invalid.
 
diff --git a/lib/lp/registry/model/milestone.py b/lib/lp/registry/model/milestone.py
index aaf2106..4c382eb 100644
--- a/lib/lp/registry/model/milestone.py
+++ b/lib/lp/registry/model/milestone.py
@@ -13,10 +13,10 @@ __all__ = [
     ]
 
 import datetime
+import http.client
 from operator import itemgetter
 
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from storm.expr import (
     And,
     Desc,
@@ -124,7 +124,7 @@ class HasMilestonesMixin:
     milestones = property(_get_milestones)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class MultipleProductReleases(Exception):
     """Raised when a second ProductRelease is created for a milestone."""
 
@@ -132,7 +132,7 @@ class MultipleProductReleases(Exception):
         super(MultipleProductReleases, self).__init__(msg)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidTags(Exception):
     """Raised when tags are invalid."""
 
diff --git a/lib/lp/registry/model/product.py b/lib/lp/registry/model/product.py
index 49e591b..5956904 100644
--- a/lib/lp/registry/model/product.py
+++ b/lib/lp/registry/model/product.py
@@ -12,6 +12,7 @@ __all__ = [
 
 
 import datetime
+import http.client
 import itertools
 import operator
 
@@ -19,7 +20,6 @@ from lazr.lifecycle.event import ObjectModifiedEvent
 from lazr.restful.declarations import error_status
 from lazr.restful.utils import safe_hasattr
 import pytz
-from six.moves import http_client
 from storm.expr import (
     And,
     Coalesce,
@@ -258,7 +258,7 @@ def get_license_status(license_approved, project_reviewed, licenses):
         return LicenseStatus.OPEN_SOURCE
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class UnDeactivateable(Exception):
     """Raised when a project is requested to deactivate but can not."""
 
diff --git a/lib/lp/registry/scripts/distributionmirror_prober.py b/lib/lp/registry/scripts/distributionmirror_prober.py
index a9eb8e9..b48fa7a 100644
--- a/lib/lp/registry/scripts/distributionmirror_prober.py
+++ b/lib/lp/registry/scripts/distributionmirror_prober.py
@@ -6,6 +6,7 @@ __all__ = [
     ]
 
 from datetime import datetime
+import http.client
 import io
 import itertools
 import logging
@@ -18,7 +19,6 @@ from OpenSSL.SSL import (
     )
 import requests
 import six
-from six.moves import http_client
 from six.moves.urllib.parse import (
     unquote,
     urljoin,
@@ -166,7 +166,7 @@ class ProberProtocol(HTTPClient):
         # same here.
         try:
             status = int(status)
-            if status == http_client.OK:
+            if status == http.client.OK:
                 self.factory.succeeded(status)
             else:
                 self.factory.failed(Failure(BadResponseCode(status)))
@@ -195,7 +195,7 @@ class HTTPSProbeFailureHandler:
         for HTTP responses.
         """
         status = response.code
-        if status == http_client.OK:
+        if status == http.client.OK:
             return response
         else:
             raise BadResponseCode(status, response)
@@ -244,8 +244,8 @@ class RedirectAwareProberProtocol(ProberProtocol):
 
     # The different redirect statuses that I handle.
     handled_redirect_statuses = (
-        http_client.MOVED_PERMANENTLY, http_client.FOUND,
-        http_client.SEE_OTHER)
+        http.client.MOVED_PERMANENTLY, http.client.FOUND,
+        http.client.SEE_OTHER)
 
     def handleHeader(self, key, value):
         key = key.lower()
diff --git a/lib/lp/registry/tests/test_distributionmirror_prober.py b/lib/lp/registry/tests/test_distributionmirror_prober.py
index 539ae7b..c2d89d5 100644
--- a/lib/lp/registry/tests/test_distributionmirror_prober.py
+++ b/lib/lp/registry/tests/test_distributionmirror_prober.py
@@ -4,6 +4,7 @@
 """distributionmirror-prober tests."""
 
 from datetime import datetime
+import http.client
 import logging
 import os
 import re
@@ -13,7 +14,6 @@ from fixtures import MockPatchObject
 from lazr.uri import URI
 import responses
 import six
-from six.moves import http_client
 from testtools.matchers import (
     ContainsDict,
     Equals,
@@ -242,7 +242,7 @@ class TestProberHTTPSProtocolAndFactory(TestCase):
         deferred = prober.probe()
 
         def got_result(result):
-            self.assertEqual(http_client.OK, result.code)
+            self.assertEqual(http.client.OK, result.code)
             expected_url = 'https://localhost:%s/valid-mirror/file' % self.port
             self.assertEqual(
                 expected_url.encode('UTF-8'), result.request.absoluteURI)
@@ -409,7 +409,7 @@ class TestProberProtocolAndFactory(TestCase):
             self.assertEqual(1, prober.redirection_count)
             new_url = 'http://localhost:%s/valid-mirror/file' % self.port
             self.assertEqual(new_url, prober.url)
-            self.assertEqual(http_client.OK, result)
+            self.assertEqual(http.client.OK, result)
 
         return deferred.addBoth(got_result)
 
@@ -430,7 +430,7 @@ class TestProberProtocolAndFactory(TestCase):
 
         def got_result(result):
             self.assertEqual(
-                http_client.OK, result,
+                http.client.OK, result,
                 "Expected a '200' status but got %r" % result)
 
         return d.addCallback(got_result)
@@ -907,7 +907,7 @@ class TestMirrorCDImageProberCallbacks(TestCaseWithFactory):
 
     def test_mirrorcdimageseries_creation_and_deletion_some_404s(self):
         not_all_success = [
-            (defer.FAILURE, Failure(BadResponseCode(http_client.NOT_FOUND))),
+            (defer.FAILURE, Failure(BadResponseCode(http.client.NOT_FOUND))),
             (defer.SUCCESS, '200')]
         callbacks = self.makeMirrorProberCallbacks()
         all_success = [(defer.SUCCESS, '200'), (defer.SUCCESS, '200')]
@@ -938,7 +938,7 @@ class TestMirrorCDImageProberCallbacks(TestCaseWithFactory):
                 InvalidHTTPSCertificate,
                 InvalidHTTPSCertificateSkipped,
                 ]))
-        exceptions = [BadResponseCode(http_client.NOT_FOUND),
+        exceptions = [BadResponseCode(http.client.NOT_FOUND),
                       ProberTimeout('http://localhost/', 5),
                       ConnectionSkipped(),
                       RedirectToDifferentFile('/foo', '/bar'),
@@ -997,7 +997,7 @@ class TestArchiveMirrorProberCallbacks(TestCaseWithFactory):
             self.fail("A timeout shouldn't be propagated. Got %s" % e)
         try:
             callbacks.deleteMirrorSeries(
-                Failure(BadResponseCode(http_client.INTERNAL_SERVER_ERROR)))
+                Failure(BadResponseCode(http.client.INTERNAL_SERVER_ERROR)))
         except Exception as e:
             self.fail(
                 "A bad response code shouldn't be propagated. Got %s" % e)
@@ -1028,7 +1028,7 @@ class TestArchiveMirrorProberCallbacks(TestCaseWithFactory):
     def test_mirrorseries_creation_and_deletion(self):
         callbacks = self.makeMirrorProberCallbacks()
         mirror_distro_series_source = callbacks.ensureMirrorSeries(
-             str(int(http_client.OK)))
+             str(int(http.client.OK)))
         self.assertIsNot(
             mirror_distro_series_source, None,
             "If the prober gets a 200 Okay status, a new "
@@ -1036,7 +1036,7 @@ class TestArchiveMirrorProberCallbacks(TestCaseWithFactory):
             "created.")
 
         callbacks.deleteMirrorSeries(
-            Failure(BadResponseCode(http_client.NOT_FOUND)))
+            Failure(BadResponseCode(http.client.NOT_FOUND)))
         # If the prober gets a 404 status, we need to make sure there's no
         # MirrorDistroSeriesSource/MirrorDistroArchSeries referent to
         # that url
diff --git a/lib/lp/registry/tests/test_errors.py b/lib/lp/registry/tests/test_errors.py
index a896211..af7202c 100644
--- a/lib/lp/registry/tests/test_errors.py
+++ b/lib/lp/registry/tests/test_errors.py
@@ -3,7 +3,7 @@
 
 """Tests for registry errors."""
 
-from six.moves.http_client import (
+from http.client import (
     BAD_REQUEST,
     CONFLICT,
     FORBIDDEN,
diff --git a/lib/lp/registry/tests/test_team_webservice.py b/lib/lp/registry/tests/test_team_webservice.py
index f738b29..024b3a3 100644
--- a/lib/lp/registry/tests/test_team_webservice.py
+++ b/lib/lp/registry/tests/test_team_webservice.py
@@ -1,11 +1,12 @@
 # Copyright 2010-2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
+import http.client
+
 from lazr.restfulclient.errors import (
     HTTPError,
     Unauthorized,
     )
-from six.moves import http_client
 import transaction
 
 from lp.app.enums import InformationType
@@ -46,7 +47,7 @@ class TestTeamJoining(TestCaseWithFactory):
             HTTPError,
             person.join,
             team='test-team')
-        self.assertEqual(http_client.BAD_REQUEST, api_error.response.status)
+        self.assertEqual(http.client.BAD_REQUEST, api_error.response.status)
 
     def test_open_accepts_membership(self):
         # Calling person.join with a team that has an open membership
diff --git a/lib/lp/services/gpg/handler.py b/lib/lp/services/gpg/handler.py
index 7a84004..1f04851 100644
--- a/lib/lp/services/gpg/handler.py
+++ b/lib/lp/services/gpg/handler.py
@@ -11,6 +11,7 @@ __all__ = [
 import atexit
 from contextlib import contextmanager
 from datetime import datetime
+import http.client
 from io import BytesIO
 import os
 import shutil
@@ -24,7 +25,6 @@ from lazr.restful.utils import get_current_browser_request
 import pytz
 import requests
 import six
-from six.moves import http_client
 from six.moves.urllib.parse import urlencode
 from zope.component import getUtility
 from zope.interface import implementer
@@ -490,7 +490,7 @@ class GPGHandler:
         keyserver_http_url = '%s:%s' % (
             config.gpghandler.host, config.gpghandler.port)
 
-        conn = http_client.HTTPConnection(keyserver_http_url)
+        conn = http.client.HTTPConnection(keyserver_http_url)
         params = urlencode({'keytext': content})
         headers = {
             "Content-type": "application/x-www-form-urlencoded",
@@ -504,7 +504,7 @@ class GPGHandler:
                 'Could not reach keyserver at http://%s %s' % (
                     keyserver_http_url, str(err)))
 
-        assert conn.getresponse().status == http_client.OK, (
+        assert conn.getresponse().status == http.client.OK, (
             'Keyserver POST failed')
 
         conn.close()
diff --git a/lib/lp/services/gpg/interfaces.py b/lib/lp/services/gpg/interfaces.py
index d6f0f73..90f780e 100644
--- a/lib/lp/services/gpg/interfaces.py
+++ b/lib/lp/services/gpg/interfaces.py
@@ -24,6 +24,7 @@ __all__ = [
     'valid_keyid',
     ]
 
+import http.client
 import os.path
 import re
 
@@ -32,7 +33,6 @@ from lazr.enum import (
     DBItem,
     )
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -143,7 +143,7 @@ class GPGKeyNotFoundError(Exception):
         super(GPGKeyNotFoundError, self).__init__(message)
 
 
-@error_status(http_client.INTERNAL_SERVER_ERROR)
+@error_status(http.client.INTERNAL_SERVER_ERROR)
 class GPGKeyTemporarilyNotFoundError(GPGKeyNotFoundError):
     """The GPG key with the given fingerprint was not found on the keyserver.
 
@@ -158,7 +158,7 @@ class GPGKeyTemporarilyNotFoundError(GPGKeyNotFoundError):
             fingerprint, message)
 
 
-@error_status(http_client.NOT_FOUND)
+@error_status(http.client.NOT_FOUND)
 class GPGKeyDoesNotExistOnServer(GPGKeyNotFoundError):
     """The GPG key with the given fingerprint was not found on the keyserver.
 
diff --git a/lib/lp/services/identity/interfaces/account.py b/lib/lp/services/identity/interfaces/account.py
index 60521bf..63034c5 100644
--- a/lib/lp/services/identity/interfaces/account.py
+++ b/lib/lp/services/identity/interfaces/account.py
@@ -17,12 +17,13 @@ __all__ = [
     'INACTIVE_ACCOUNT_STATUSES',
     ]
 
+import http.client
+
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
     )
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -40,12 +41,12 @@ from lp.app.validators import LaunchpadValidationError
 from lp.services.fields import StrippedTextLine
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class AccountSuspendedError(Exception):
     """The account being accessed has been suspended."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class AccountDeceasedError(Exception):
     """The account being accessed belongs to a deceased user."""
 
diff --git a/lib/lp/services/identity/interfaces/emailaddress.py b/lib/lp/services/identity/interfaces/emailaddress.py
index 6d8799f..ef9bb14 100644
--- a/lib/lp/services/identity/interfaces/emailaddress.py
+++ b/lib/lp/services/identity/interfaces/emailaddress.py
@@ -11,6 +11,8 @@ __all__ = [
     'InvalidEmailAddress',
     'VALID_EMAIL_STATUSES']
 
+import http.client
+
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -21,7 +23,6 @@ from lazr.restful.declarations import (
     exported_as_webservice_entry,
     )
 from lazr.restful.fields import Reference
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Choice,
@@ -37,7 +38,7 @@ class InvalidEmailAddress(Exception):
     """The email address is not valid."""
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class EmailAddressAlreadyTaken(Exception):
     """The email address is already registered in Launchpad."""
 
diff --git a/lib/lp/services/librarian/client.py b/lib/lp/services/librarian/client.py
index 434e2f2..17d40d9 100644
--- a/lib/lp/services/librarian/client.py
+++ b/lib/lp/services/librarian/client.py
@@ -12,6 +12,7 @@ __all__ = [
 
 
 import hashlib
+import http.client
 import select
 import socket
 from socket import (
@@ -23,7 +24,6 @@ import time
 
 from lazr.restful.utils import get_current_browser_request
 import six
-from six.moves import http_client
 from six.moves.urllib.error import (
     HTTPError,
     URLError,
@@ -344,7 +344,7 @@ class _File:
                 # from a non-chunked-transfer-coding resource.  Check this
                 # manually.
                 if not s and chunksize != 0 and self.length:
-                    raise http_client.IncompleteRead(s, expected=self.length)
+                    raise http.client.IncompleteRead(s, expected=self.length)
             return s
         finally:
             action.finish()
diff --git a/lib/lp/services/librarian/interfaces/client.py b/lib/lp/services/librarian/interfaces/client.py
index cea13e8..a57435f 100644
--- a/lib/lp/services/librarian/interfaces/client.py
+++ b/lib/lp/services/librarian/interfaces/client.py
@@ -12,10 +12,10 @@ __all__ = [
     'UploadFailed',
     ]
 
+import http.client
 import signal
 
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import Interface
 
 
@@ -35,7 +35,7 @@ class DownloadFailed(LibrarianFailure):
     pass
 
 
-@error_status(http_client.REQUEST_TIMEOUT)
+@error_status(http.client.REQUEST_TIMEOUT)
 class LibrarianServerError(Exception):
     """An error indicating that the Librarian server is not responding."""
 
diff --git a/lib/lp/services/librarian/tests/test_client.py b/lib/lp/services/librarian/tests/test_client.py
index a5528f9..5ecb389 100644
--- a/lib/lp/services/librarian/tests/test_client.py
+++ b/lib/lp/services/librarian/tests/test_client.py
@@ -2,6 +2,7 @@
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 import hashlib
+import http.client
 import io
 import os
 import re
@@ -14,7 +15,6 @@ from fixtures import (
     EnvironmentVariable,
     TempDir,
     )
-from six.moves import http_client
 from six.moves.urllib.error import (
     HTTPError,
     URLError,
@@ -172,7 +172,7 @@ class LibrarianFileWrapperTestCase(TestCase):
 
     def test_unbounded_read_incorrect_length(self):
         file = self.makeFile(extra_content_length=1)
-        with ExpectedException(http_client.IncompleteRead):
+        with ExpectedException(http.client.IncompleteRead):
             # Python 3 notices the short response on the first read.
             self.assertEqual(b"abcdef", file.read())
             # Python 2 only notices the short response on the next read.
@@ -188,7 +188,7 @@ class LibrarianFileWrapperTestCase(TestCase):
         file = self.makeFile(extra_content_length=1)
         self.assertEqual(b"abcd", file.read(chunksize=4))
         self.assertEqual(b"ef", file.read(chunksize=4))
-        self.assertRaises(http_client.IncompleteRead, file.read, chunksize=4)
+        self.assertRaises(http.client.IncompleteRead, file.read, chunksize=4)
 
 
 class EchoServer(threading.Thread):
@@ -521,4 +521,4 @@ class TestWebServiceErrors(unittest.TestCase):
 
     def test_LibrarianServerError_timeout(self):
         error_view = create_webservice_error_view(LibrarianServerError())
-        self.assertEqual(http_client.REQUEST_TIMEOUT, error_view.status)
+        self.assertEqual(http.client.REQUEST_TIMEOUT, error_view.status)
diff --git a/lib/lp/services/librarianserver/tests/test_web.py b/lib/lp/services/librarianserver/tests/test_web.py
index 7ca8cb8..6325163 100644
--- a/lib/lp/services/librarianserver/tests/test_web.py
+++ b/lib/lp/services/librarianserver/tests/test_web.py
@@ -4,6 +4,7 @@
 from datetime import datetime
 from gzip import GzipFile
 import hashlib
+import http.client
 from io import BytesIO
 import os
 import unittest
@@ -11,7 +12,6 @@ import unittest
 from lazr.uri import URI
 import pytz
 import requests
-from six.moves import http_client
 from six.moves.urllib.parse import urlparse
 from storm.expr import SQL
 from testtools.matchers import EndsWith
@@ -358,7 +358,7 @@ class LibrarianWebTestCase(LibrarianWebTestMixin, TestCaseWithFactory):
         response.raise_for_status()
         # Use the network level protocol because DNS resolution won't work
         # here (no wildcard support)
-        connection = http_client.HTTPConnection(
+        connection = http.client.HTTPConnection(
             config.librarian.download_host,
             config.librarian.download_port)
         # A valid subdomain based URL must work.
diff --git a/lib/lp/services/oauth/interfaces.py b/lib/lp/services/oauth/interfaces.py
index fba5cc6..75dc076 100644
--- a/lib/lp/services/oauth/interfaces.py
+++ b/lib/lp/services/oauth/interfaces.py
@@ -15,8 +15,9 @@ __all__ = [
     'TokenException',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -266,7 +267,7 @@ class IOAuthSignedRequest(Interface):
 # so they may be raised but will not cause an OOPS to be generated.  The
 # client will see them as an UNAUTHORIZED error.
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class _TokenException(Exception):
     """Base class for token exceptions."""
 
diff --git a/lib/lp/services/tests/test_xmlrpc.py b/lib/lp/services/tests/test_xmlrpc.py
index 5db747d..bbe1ff9 100644
--- a/lib/lp/services/tests/test_xmlrpc.py
+++ b/lib/lp/services/tests/test_xmlrpc.py
@@ -3,7 +3,7 @@
 
 """Test the generic and/or shared xmlrpc code that Launchpad provides."""
 
-from six.moves import http_client
+import http.client
 
 from lp.services.xmlrpc import Transport
 from lp.testing import TestCase
@@ -17,7 +17,7 @@ class TestTransport(TestCase):
 
     def test_default_initialization(self):
         transport = Transport()
-        conn = http_client.HTTPConnection('localhost')
+        conn = http.client.HTTPConnection('localhost')
         self.assertEqual(conn.timeout, transport.timeout)
 
     def test_custom_initialization(self):
diff --git a/lib/lp/services/webapp/error.py b/lib/lp/services/webapp/error.py
index 54cf66d..4458601 100644
--- a/lib/lp/services/webapp/error.py
+++ b/lib/lp/services/webapp/error.py
@@ -12,12 +12,11 @@ __all__ = [
     'UnexpectedFormDataView',
     ]
 
-
+import http.client
 import sys
 import traceback
 
 import six
-from six.moves import http_client
 from zope.browser.interfaces import ISystemErrorView
 from zope.browserpage import ViewPageTemplateFile
 from zope.component import getUtility
@@ -46,7 +45,7 @@ class SystemErrorView(LaunchpadView):
         'templates/oops-veryplain.pt')
 
     # Override this in subclasses.  A value of None means "don't set this"
-    response_code = http_client.INTERNAL_SERVER_ERROR
+    response_code = http.client.INTERNAL_SERVER_ERROR
 
     show_opengraph_meta = False
     show_tracebacks = False
@@ -186,7 +185,7 @@ class NotFoundView(SystemErrorView):
 
     page_title = 'Error: Page not found'
 
-    response_code = http_client.NOT_FOUND
+    response_code = http.client.NOT_FOUND
 
     def __call__(self):
         return self.index()
@@ -217,14 +216,14 @@ class GoneView(NotFoundView):
 
     page_title = 'Error: Page gone'
 
-    response_code = http_client.GONE
+    response_code = http.client.GONE
 
 
 class RequestExpiredView(SystemErrorView):
 
     page_title = 'Error: Timeout'
 
-    response_code = http_client.SERVICE_UNAVAILABLE
+    response_code = http.client.SERVICE_UNAVAILABLE
 
     def __init__(self, context, request):
         SystemErrorView.__init__(self, context, request)
@@ -239,7 +238,7 @@ class InvalidBatchSizeView(SystemErrorView):
 
     page_title = "Error: Invalid Batch Size"
 
-    response_code = http_client.BAD_REQUEST
+    response_code = http.client.BAD_REQUEST
 
     def isSystemError(self):
         """We don't need to log these errors in the SiteLog."""
@@ -257,7 +256,7 @@ class TranslationUnavailableView(SystemErrorView):
 
     page_title = 'Error: Translation page is not available'
 
-    response_code = http_client.SERVICE_UNAVAILABLE
+    response_code = http.client.SERVICE_UNAVAILABLE
 
     def __call__(self):
         return self.index()
@@ -266,12 +265,12 @@ class TranslationUnavailableView(SystemErrorView):
 class NoReferrerErrorView(SystemErrorView):
     """View rendered when a POST request does not include a REFERER header."""
 
-    response_code = http_client.FORBIDDEN
+    response_code = http.client.FORBIDDEN
 
 
 class OpenIdDiscoveryFailureView(SystemErrorView):
 
-    response_code = http_client.SERVICE_UNAVAILABLE
+    response_code = http.client.SERVICE_UNAVAILABLE
 
     def isSystemError(self):
         """We don't need to log these errors in the SiteLog."""
@@ -280,7 +279,7 @@ class OpenIdDiscoveryFailureView(SystemErrorView):
 
 class DisconnectionErrorView(SystemErrorView):
 
-    response_code = http_client.SERVICE_UNAVAILABLE
+    response_code = http.client.SERVICE_UNAVAILABLE
     reason = u'our database being temporarily offline'
 
 
diff --git a/lib/lp/services/webapp/publisher.py b/lib/lp/services/webapp/publisher.py
index 4e8c105..8b0761b 100644
--- a/lib/lp/services/webapp/publisher.py
+++ b/lib/lp/services/webapp/publisher.py
@@ -26,6 +26,7 @@ __all__ = [
     ]
 
 from cgi import FieldStorage
+import http.client
 import re
 from wsgiref.headers import Headers
 
@@ -40,7 +41,6 @@ from lazr.restful.tales import WebLayerAPI
 from lazr.restful.utils import get_current_browser_request
 import simplejson
 import six
-from six.moves import http_client
 from six.moves.urllib.parse import urlparse
 from zope.app.publisher.xmlrpc import IMethodPublisher
 from zope.component import (
@@ -97,7 +97,7 @@ from lp.services.webapp.vhosts import allvhosts
 
 # Monkeypatch NotFound to always avoid generating OOPS
 # from NotFound in web service calls.
-error_status(http_client.NOT_FOUND)(NotFound)
+error_status(http.client.NOT_FOUND)(NotFound)
 
 # Used to match zope namespaces eg ++model++.
 RESERVED_NAMESPACE = re.compile('\\+\\+.*\\+\\+')
diff --git a/lib/lp/services/webapp/tests/test_error.py b/lib/lp/services/webapp/tests/test_error.py
index 0bd9c22..1293f94 100644
--- a/lib/lp/services/webapp/tests/test_error.py
+++ b/lib/lp/services/webapp/tests/test_error.py
@@ -3,14 +3,13 @@
 
 """Test error views."""
 
-
+import http.client
 import logging
 import socket
 import time
 
 from fixtures import FakeLogger
 import psycopg2
-from six.moves import http_client
 from six.moves.urllib.error import HTTPError
 from storm.exceptions import (
     DisconnectionError,
@@ -111,7 +110,7 @@ class TestDatabaseErrorViews(TestCase):
                 browser.open(url)
                 return
             except HTTPError as e:
-                if e.code != http_client.SERVICE_UNAVAILABLE:
+                if e.code != http.client.SERVICE_UNAVAILABLE:
                     raise
             time.sleep(1)
         else:
@@ -246,7 +245,7 @@ class TestDatabaseErrorViews(TestCase):
         browser.raiseHttpErrors = False
         browser.open(url)
         self.assertEqual(
-            http_client.SERVICE_UNAVAILABLE,
+            http.client.SERVICE_UNAVAILABLE,
             int(browser.headers['Status'].split(' ', 1)[0]))
         self.assertThat(
             browser.contents, Contains(OperationalErrorView.reason))
diff --git a/lib/lp/services/webapp/tests/test_errorlog.py b/lib/lp/services/webapp/tests/test_errorlog.py
index 1961298..587f18f 100644
--- a/lib/lp/services/webapp/tests/test_errorlog.py
+++ b/lib/lp/services/webapp/tests/test_errorlog.py
@@ -3,6 +3,7 @@
 
 """Tests for error logging & OOPS reporting."""
 
+import http.client
 import sys
 from textwrap import dedent
 import traceback
@@ -13,7 +14,6 @@ from lazr.restful.declarations import error_status
 import oops_amqp
 import pytz
 import six
-from six.moves import http_client
 from talisker.logs import logging_context
 import testtools
 from timeline.timeline import Timeline
@@ -262,7 +262,7 @@ class TestErrorReportingUtility(TestCaseWithFactory):
 
         # Exceptions with a error_status in the 500 range result
         # in OOPSes.
-        @error_status(http_client.INTERNAL_SERVER_ERROR)
+        @error_status(http.client.INTERNAL_SERVER_ERROR)
         class InternalServerError(Exception):
             pass
         try:
@@ -273,7 +273,7 @@ class TestErrorReportingUtility(TestCaseWithFactory):
 
         # Exceptions with any other error_status do not result
         # in OOPSes.
-        @error_status(http_client.BAD_REQUEST)
+        @error_status(http.client.BAD_REQUEST)
         class BadDataError(Exception):
             pass
         try:
diff --git a/lib/lp/services/webapp/tests/test_login.py b/lib/lp/services/webapp/tests/test_login.py
index 9abc359..7817636 100644
--- a/lib/lp/services/webapp/tests/test_login.py
+++ b/lib/lp/services/webapp/tests/test_login.py
@@ -15,6 +15,7 @@ from datetime import (
     datetime,
     timedelta,
     )
+import http.client
 import unittest
 
 from openid.consumer.consumer import (
@@ -26,7 +27,6 @@ from openid.extensions import (
     sreg,
     )
 from openid.yadis.discover import DiscoveryFailure
-from six.moves import http_client
 from six.moves.urllib.error import HTTPError
 from six.moves.urllib.parse import (
     parse_qsl,
@@ -241,7 +241,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
                 person.account, email=test_email)
         self.assertTrue(view.login_called)
         response = view.request.response
-        self.assertEqual(http_client.TEMPORARY_REDIRECT, response.getStatus())
+        self.assertEqual(http.client.TEMPORARY_REDIRECT, response.getStatus())
         self.assertEqual(view.request.form['starting_url'],
                          response.getHeader('Location'))
         # The 'last_write' flag was not updated (unlike in the other test
@@ -410,7 +410,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
             view, html = self._createAndRenderView(openid_response)
         self.assertTrue(view.login_called)
         response = view.request.response
-        self.assertEqual(http_client.TEMPORARY_REDIRECT, response.getStatus())
+        self.assertEqual(http.client.TEMPORARY_REDIRECT, response.getStatus())
         self.assertEqual(view.request.form['starting_url'],
                          response.getHeader('Location'))
         self.assertEqual(AccountStatus.ACTIVE, person.account.status)
@@ -589,7 +589,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
             view_class=StubbedOpenIDCallbackViewLoggedIn)
         self.assertFalse(view.login_called)
         response = view.request.response
-        self.assertEqual(http_client.TEMPORARY_REDIRECT, response.getStatus())
+        self.assertEqual(http.client.TEMPORARY_REDIRECT, response.getStatus())
         self.assertEqual(view.request.form['starting_url'],
                          response.getHeader('Location'))
         notification_msg = view.request.response.notifications[0].message
@@ -637,7 +637,7 @@ class TestOpenIDCallbackRedirects(TestCaseWithFactory):
         view.initialize()
         view._redirect()
         self.assertEqual(
-            http_client.TEMPORARY_REDIRECT, view.request.response.getStatus())
+            http.client.TEMPORARY_REDIRECT, view.request.response.getStatus())
         self.assertEqual(
             view.request.response.getHeader('Location'), self.STARTING_URL)
 
@@ -651,7 +651,7 @@ class TestOpenIDCallbackRedirects(TestCaseWithFactory):
         view.initialize()
         view._redirect()
         self.assertEqual(
-            http_client.TEMPORARY_REDIRECT, view.request.response.getStatus())
+            http.client.TEMPORARY_REDIRECT, view.request.response.getStatus())
         self.assertEqual(
             view.request.response.getHeader('Location'), self.STARTING_URL)
 
@@ -663,7 +663,7 @@ class TestOpenIDCallbackRedirects(TestCaseWithFactory):
         view.initialize()
         view._redirect()
         self.assertEqual(
-            http_client.TEMPORARY_REDIRECT, view.request.response.getStatus())
+            http.client.TEMPORARY_REDIRECT, view.request.response.getStatus())
         self.assertEqual(
             view.request.response.getHeader('Location'), self.APPLICATION_URL)
 
@@ -690,12 +690,12 @@ class TestOpenIDReplayAttack(TestCaseWithFactory):
         self.assertEqual('Login', browser.title)
         fill_login_form_and_submit(browser, 'test@xxxxxxxxxxxxx')
         self.assertEqual(
-            http_client.FOUND, int(browser.headers['Status'].split(' ', 1)[0]))
+            http.client.FOUND, int(browser.headers['Status'].split(' ', 1)[0]))
         callback_url = browser.headers['Location']
         self.assertIn('+openid-callback', callback_url)
         browser.open(callback_url)
         self.assertEqual(
-            http_client.TEMPORARY_REDIRECT,
+            http.client.TEMPORARY_REDIRECT,
             int(browser.headers['Status'].split(' ', 1)[0]))
         browser.open(browser.headers['Location'])
         login_status = extract_text(
diff --git a/lib/lp/services/webhooks/interfaces.py b/lib/lp/services/webhooks/interfaces.py
index 142d719..a63caf1 100644
--- a/lib/lp/services/webhooks/interfaces.py
+++ b/lib/lp/services/webhooks/interfaces.py
@@ -20,6 +20,8 @@ __all__ = [
     'ValidWebhookEventTypeVocabulary',
     ]
 
+import http.client
+
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -39,7 +41,6 @@ from lazr.restful.fields import (
     )
 from lazr.restful.interface import copy_field
 import six
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -81,7 +82,7 @@ WEBHOOK_EVENT_TYPES = {
     }
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class WebhookFeatureDisabled(Exception):
     """Only certain users can create new webhooks."""
 
diff --git a/lib/lp/snappy/interfaces/snap.py b/lib/lp/snappy/interfaces/snap.py
index 9f22cac..957a378 100644
--- a/lib/lp/snappy/interfaces/snap.py
+++ b/lib/lp/snappy/interfaces/snap.py
@@ -36,6 +36,8 @@ __all__ = [
     'SnapPrivateFeatureDisabled',
     ]
 
+import http.client
+
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -64,7 +66,6 @@ from lazr.restful.fields import (
     ReferenceChoice,
     )
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -127,7 +128,7 @@ SNAP_TESTING_FLAGS = {
     }
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class SnapBuildAlreadyPending(Exception):
     """A build was requested when an identical build was already pending."""
 
@@ -136,7 +137,7 @@ class SnapBuildAlreadyPending(Exception):
             "An identical build of this snap package is already pending.")
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class SnapBuildArchiveOwnerMismatch(Forbidden):
     """Builds against private archives require that owners match.
 
@@ -154,7 +155,7 @@ class SnapBuildArchiveOwnerMismatch(Forbidden):
             "if the snap package owner and the archive owner are equal.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class SnapBuildDisallowedArchitecture(Exception):
     """A build was requested for a disallowed architecture."""
 
@@ -164,7 +165,7 @@ class SnapBuildDisallowedArchitecture(Exception):
             (das.distroseries.getSuite(pocket), das.architecturetag))
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class SnapPrivateFeatureDisabled(Unauthorized):
     """Only certain users can create private snap objects."""
 
@@ -173,7 +174,7 @@ class SnapPrivateFeatureDisabled(Unauthorized):
             "You do not have permission to create private snaps")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DuplicateSnapName(Exception):
     """Raised for snap packages with duplicate name/owner."""
 
@@ -182,7 +183,7 @@ class DuplicateSnapName(Exception):
             "There is already a snap package with the same name and owner.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class SnapNotOwner(Unauthorized):
     """The registrant/requester is not the owner or a member of its team."""
 
@@ -192,7 +193,7 @@ class NoSuchSnap(NameLookupFailed):
     _message_prefix = "No such snap package with this owner"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoSourceForSnap(Exception):
     """Snap packages must have a source (Bazaar or Git branch)."""
 
@@ -202,12 +203,12 @@ class NoSourceForSnap(Exception):
             "branch.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BadSnapSource(Exception):
     """The elements of the source for a snap package are inconsistent."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class SnapPrivacyMismatch(Exception):
     """Snap package privacy does not match its content."""
 
@@ -217,7 +218,7 @@ class SnapPrivacyMismatch(Exception):
             "Snap recipe contains private information and cannot be public.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class SnapPrivacyPillarError(Exception):
     """Private Snaps should be based in a pillar."""
 
@@ -230,7 +231,7 @@ class BadSnapSearchContext(Exception):
     """The context is not valid for a snap package search."""
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotModifySnapProcessor(Exception):
     """Tried to enable or disable a restricted processor on an snap package."""
 
@@ -243,22 +244,22 @@ class CannotModifySnapProcessor(Exception):
             self._fmt % {'processor': processor.name})
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotAuthorizeStoreUploads(Exception):
     """Cannot authorize uploads of a snap package to the store."""
 
 
-@error_status(http_client.INTERNAL_SERVER_ERROR)
+@error_status(http.client.INTERNAL_SERVER_ERROR)
 class SnapAuthorizationBadGeneratedMacaroon(Exception):
     """The macaroon generated to authorize store uploads is unusable."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class BadMacaroon(Exception):
     """A macaroon supplied by the user is invalid."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotRequestAutoBuilds(Exception):
     """Snap package is not configured for automatic builds."""
 
diff --git a/lib/lp/snappy/interfaces/snapbase.py b/lib/lp/snappy/interfaces/snapbase.py
index 05266da..ace5443 100644
--- a/lib/lp/snappy/interfaces/snapbase.py
+++ b/lib/lp/snappy/interfaces/snapbase.py
@@ -10,6 +10,8 @@ __all__ = [
     "NoSuchSnapBase",
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     call_with,
     collection_default_content,
@@ -33,7 +35,6 @@ from lazr.restful.fields import (
     )
 from lazr.restful.interface import copy_field
 import six
-from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import Interface
 from zope.schema import (
@@ -64,7 +65,7 @@ class NoSuchSnapBase(NameLookupFailed):
     _message_prefix = "No such base"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteSnapBase(Exception):
     """The base cannot be deleted at this time."""
 
diff --git a/lib/lp/snappy/interfaces/snapbuild.py b/lib/lp/snappy/interfaces/snapbuild.py
index a49dd24..1d7c050 100644
--- a/lib/lp/snappy/interfaces/snapbuild.py
+++ b/lib/lp/snappy/interfaces/snapbuild.py
@@ -12,6 +12,8 @@ __all__ = [
     'SnapBuildStoreUploadStatus',
     ]
 
+import http.client
+
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -29,7 +31,6 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
-from six.moves import http_client
 from zope.component.interfaces import IObjectEvent
 from zope.interface import (
     Attribute,
@@ -62,7 +63,7 @@ from lp.soyuz.interfaces.archive import IArchive
 from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotScheduleStoreUpload(Exception):
     """This build cannot be uploaded to the store."""
 
diff --git a/lib/lp/snappy/interfaces/snapstoreclient.py b/lib/lp/snappy/interfaces/snapstoreclient.py
index 56ed4d2..30740d2 100644
--- a/lib/lp/snappy/interfaces/snapstoreclient.py
+++ b/lib/lp/snappy/interfaces/snapstoreclient.py
@@ -17,8 +17,9 @@ __all__ = [
     'UploadNotScannedYetResponse',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import Interface
 
 
@@ -33,7 +34,7 @@ class SnapStoreError(Exception):
         self.can_retry = can_retry
 
 
-@error_status(http_client.INTERNAL_SERVER_ERROR)
+@error_status(http.client.INTERNAL_SERVER_ERROR)
 class BadRequestPackageUploadResponse(SnapStoreError):
     pass
 
diff --git a/lib/lp/soyuz/doc/package-diff.txt b/lib/lp/soyuz/doc/package-diff.txt
index 2c0d2c7..d39ae0c 100644
--- a/lib/lp/soyuz/doc/package-diff.txt
+++ b/lib/lp/soyuz/doc/package-diff.txt
@@ -386,8 +386,8 @@ for users to view it.
     >>> parsed_url = urlparse(diff.diff_content.http_url)
     >>> netloc, path = parsed_url[1:3]
 
-    >>> from six.moves import http_client
-    >>> con = http_client.HTTPConnection(netloc)
+    >>> import http.client
+    >>> con = http.client.HTTPConnection(netloc)
     >>> con.request("HEAD", path)
     >>> resp = con.getresponse()
 
diff --git a/lib/lp/soyuz/interfaces/archive.py b/lib/lp/soyuz/interfaces/archive.py
index f8f18f6..d01ebdf 100644
--- a/lib/lp/soyuz/interfaces/archive.py
+++ b/lib/lp/soyuz/interfaces/archive.py
@@ -52,6 +52,7 @@ __all__ = [
     'validate_external_dependencies',
     ]
 
+import http.client
 import re
 
 from lazr.restful.declarations import (
@@ -77,7 +78,6 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
-from six.moves import http_client
 from six.moves.urllib.parse import urlparse
 from zope.interface import (
     Attribute,
@@ -121,7 +121,7 @@ from lp.soyuz.interfaces.component import IComponent
 NAMED_AUTH_TOKEN_FEATURE_FLAG = u"soyuz.named_auth_token.allow_new"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class ArchiveDependencyError(Exception):
     """Raised when an `IArchiveDependency` does not fit the context archive.
 
@@ -135,12 +135,12 @@ class ArchiveDependencyError(Exception):
 
 # Exceptions used in the webservice that need to be in this file to get
 # picked up therein.
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotCopy(Exception):
     """Exception raised when a copy cannot be performed."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotSwitchPrivacy(Exception):
     """Raised when switching the privacy of an archive that has
     publishing records."""
@@ -151,17 +151,17 @@ class PocketNotFound(NameLookupFailed):
     _message_prefix = "No such pocket"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class AlreadySubscribed(Exception):
     """Raised when creating a subscription for a subscribed person."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class ArchiveNotPrivate(Exception):
     """Raised when creating an archive subscription for a public archive."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class NoTokensForTeams(Exception):
     """Raised when creating a token for a team, rather than a person."""
 
@@ -171,7 +171,7 @@ class ComponentNotFound(NameLookupFailed):
     _message_prefix = 'No such component'
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidComponent(Exception):
     """Invalid component name."""
 
@@ -191,17 +191,17 @@ class NoSuchPPA(NameLookupFailed):
     _message_prefix = "No such ppa"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class VersionRequiresName(Exception):
     """Raised on some queries when version is specified but name is not."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class ArchiveAlreadyDeleted(Exception):
     """Archive already deleted."""
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotUploadToArchive(Exception):
     """A reason for not being able to upload to an archive."""
 
@@ -218,7 +218,7 @@ class InvalidPocketForPartnerArchive(CannotUploadToArchive):
     _fmt = "Partner uploads must be for the RELEASE or PROPOSED pocket."
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotUploadToPocket(Exception):
     """Returned when a pocket is closed for uploads."""
 
@@ -228,7 +228,7 @@ class CannotUploadToPocket(Exception):
             "'%s' state." % (pocket.name, distroseries.status.name))
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class RedirectedPocket(Exception):
     """Returned for a pocket that would normally be redirected to another.
 
@@ -299,7 +299,7 @@ class CannotUploadToSeries(CannotUploadToArchive):
             distroseries=distroseries.name)
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidExternalDependencies(Exception):
     """Tried to set external dependencies to an invalid value."""
 
@@ -309,7 +309,7 @@ class InvalidExternalDependencies(Exception):
         self.errors = errors
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class CannotModifyArchiveProcessor(Exception):
     """Tried to enable or disable a restricted processor on an archive."""
 
@@ -322,13 +322,13 @@ class CannotModifyArchiveProcessor(Exception):
             self._fmt % {'processor': processor.name})
 
 
-@error_status(http_client.CONFLICT)
+@error_status(http.client.CONFLICT)
 class DuplicateTokenName(Exception):
     """Raised when creating a named token and an active token for this archive
      with this name already exists."""
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class NamedAuthTokenFeatureDisabled(Unauthorized):
     """Only certain users can create named authorization tokens."""
 
diff --git a/lib/lp/soyuz/interfaces/binarypackagebuild.py b/lib/lp/soyuz/interfaces/binarypackagebuild.py
index 0f7aeb9..3771af8 100644
--- a/lib/lp/soyuz/interfaces/binarypackagebuild.py
+++ b/lib/lp/soyuz/interfaces/binarypackagebuild.py
@@ -12,6 +12,8 @@ __all__ = [
     'UnparsableDependencies',
     ]
 
+import http.client
+
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -27,7 +29,6 @@ from lazr.restful.declarations import (
     operation_returns_entry,
     )
 from lazr.restful.fields import Reference
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -48,7 +49,7 @@ from lp.soyuz.interfaces.publishing import ISourcePackagePublishingHistory
 from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotBeRescored(Exception):
     """Raised when rescoring a build that cannot be rescored."""
     _message_prefix = "Cannot rescore build"
diff --git a/lib/lp/soyuz/interfaces/distroarchseries.py b/lib/lp/soyuz/interfaces/distroarchseries.py
index b2fd6fe..0d0ffc4 100644
--- a/lib/lp/soyuz/interfaces/distroarchseries.py
+++ b/lib/lp/soyuz/interfaces/distroarchseries.py
@@ -11,6 +11,8 @@ __all__ = [
     'IPocketChroot',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     call_with,
     error_status,
@@ -27,7 +29,6 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -53,12 +54,12 @@ from lp.soyuz.enums import DistroArchSeriesFilterSense
 from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class InvalidChrootUploaded(Exception):
     """Raised when the sha1sum of an uploaded chroot does not match."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class ChrootNotPublic(Exception):
     """Raised when trying to set a chroot from a private livefs build."""
 
@@ -66,7 +67,7 @@ class ChrootNotPublic(Exception):
         super().__init__("Cannot set chroot from a private build.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class FilterSeriesMismatch(Exception):
     """DAS and packageset distroseries do not match when setting a filter."""
 
diff --git a/lib/lp/soyuz/interfaces/livefs.py b/lib/lp/soyuz/interfaces/livefs.py
index 5a25e2f..d64dfe6 100644
--- a/lib/lp/soyuz/interfaces/livefs.py
+++ b/lib/lp/soyuz/interfaces/livefs.py
@@ -20,6 +20,8 @@ __all__ = [
     'NoSuchLiveFS',
     ]
 
+import http.client
+
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -40,7 +42,6 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Bool,
@@ -76,7 +77,7 @@ LIVEFS_FEATURE_FLAG = u"soyuz.livefs.allow_new"
 LIVEFS_WEBHOOKS_FEATURE_FLAG = u"soyuz.livefs.webhooks.enabled"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class LiveFSBuildAlreadyPending(Exception):
     """A build was requested when an identical build was already pending."""
 
@@ -86,7 +87,7 @@ class LiveFSBuildAlreadyPending(Exception):
             "pending.")
 
 
-@error_status(http_client.FORBIDDEN)
+@error_status(http.client.FORBIDDEN)
 class LiveFSBuildArchiveOwnerMismatch(Forbidden):
     """Builds into private archives require that owners match.
 
@@ -105,7 +106,7 @@ class LiveFSBuildArchiveOwnerMismatch(Forbidden):
             "equal.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class LiveFSFeatureDisabled(Unauthorized):
     """Only certain users can create new LiveFS-related objects."""
 
@@ -115,7 +116,7 @@ class LiveFSFeatureDisabled(Unauthorized):
             "new live filesystem builds.")
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DuplicateLiveFSName(Exception):
     """Raised for live filesystems with duplicate name/owner/distroseries."""
 
@@ -125,7 +126,7 @@ class DuplicateLiveFSName(Exception):
             "and distroseries.")
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class LiveFSNotOwner(Unauthorized):
     """The registrant/requester is not the owner or a member of its team."""
 
@@ -135,7 +136,7 @@ class NoSuchLiveFS(NameLookupFailed):
     _message_prefix = "No such live filesystem with this owner/distroseries"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class CannotDeleteLiveFS(Exception):
     """This live filesystem cannot be deleted."""
 
diff --git a/lib/lp/soyuz/interfaces/packagediff.py b/lib/lp/soyuz/interfaces/packagediff.py
index c7cab92..686a1b3 100644
--- a/lib/lp/soyuz/interfaces/packagediff.py
+++ b/lib/lp/soyuz/interfaces/packagediff.py
@@ -9,8 +9,9 @@ __all__ = [
     'PackageDiffAlreadyRequested',
     ]
 
+import http.client
+
 from lazr.restful.declarations import error_status
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -26,7 +27,7 @@ from lp.services.librarian.interfaces import ILibraryFileAlias
 from lp.soyuz.enums import PackageDiffStatus
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class PackageDiffRequestException(Exception):
     """Base class for package diff request errors."""
 
diff --git a/lib/lp/soyuz/interfaces/packageset.py b/lib/lp/soyuz/interfaces/packageset.py
index cc88b72..c1254cf 100644
--- a/lib/lp/soyuz/interfaces/packageset.py
+++ b/lib/lp/soyuz/interfaces/packageset.py
@@ -10,6 +10,8 @@ __all__ = [
     'NoSuchPackageSet',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     collection_default_content,
     error_status,
@@ -27,7 +29,6 @@ from lazr.restful.declarations import (
     )
 from lazr.restful.fields import Reference
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Bool,
@@ -51,7 +52,7 @@ class NoSuchPackageSet(NameLookupFailed):
     _message_prefix = "No such package set (in the specified distro series)"
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DuplicatePackagesetName(Exception):
     """Raised for packagesets with the same name and distroseries."""
 
diff --git a/lib/lp/soyuz/interfaces/publishing.py b/lib/lp/soyuz/interfaces/publishing.py
index 35dff3b..16667a6 100644
--- a/lib/lp/soyuz/interfaces/publishing.py
+++ b/lib/lp/soyuz/interfaces/publishing.py
@@ -23,6 +23,8 @@ __all__ = [
     'name_priority_map',
     ]
 
+import http.client
+
 from lazr.restful.declarations import (
     call_with,
     error_status,
@@ -38,7 +40,6 @@ from lazr.restful.declarations import (
     REQUEST_USER,
     )
 from lazr.restful.fields import Reference
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -96,12 +97,12 @@ class MissingSymlinkInPool(Exception):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class OverrideError(Exception):
     """Raised when an attempt to change an override fails."""
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class DeletionError(Exception):
     """Raised when an attempt to delete a publication fails."""
 
diff --git a/lib/lp/soyuz/interfaces/queue.py b/lib/lp/soyuz/interfaces/queue.py
index f898203..a95c982 100644
--- a/lib/lp/soyuz/interfaces/queue.py
+++ b/lib/lp/soyuz/interfaces/queue.py
@@ -22,6 +22,8 @@ __all__ = [
     'QueueStateWriteProtectedError'
     ]
 
+import http.client
+
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -38,7 +40,6 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -70,7 +71,7 @@ class QueueStateWriteProtectedError(Exception):
     """
 
 
-@error_status(http_client.BAD_REQUEST)
+@error_status(http.client.BAD_REQUEST)
 class QueueInconsistentStateError(Exception):
     """Queue state machine error.
 
diff --git a/lib/lp/soyuz/tests/test_archive.py b/lib/lp/soyuz/tests/test_archive.py
index 0348fa7..1207443 100644
--- a/lib/lp/soyuz/tests/test_archive.py
+++ b/lib/lp/soyuz/tests/test_archive.py
@@ -9,13 +9,13 @@ from datetime import (
     timedelta,
     )
 import doctest
+import http.client
 import os.path
 
 from aptsources.sourceslist import SourceEntry
 from pytz import UTC
 import responses
 import six
-from six.moves import http_client
 from six.moves.urllib.parse import urlsplit
 from storm.store import Store
 from testtools.matchers import (
@@ -4087,7 +4087,7 @@ class TestGetSigningKeyData(TestCaseWithFactory):
             error = self.assertRaises(
                 GPGKeyDoesNotExistOnServer, ppa.getSigningKeyData)
         error_view = create_webservice_error_view(error)
-        self.assertEqual(http_client.NOT_FOUND, error_view.status)
+        self.assertEqual(http.client.NOT_FOUND, error_view.status)
 
     @responses.activate
     def test_getSigningKeyData_keyserver_failure(self):
@@ -4100,7 +4100,7 @@ class TestGetSigningKeyData(TestCaseWithFactory):
             error = self.assertRaises(
                 GPGKeyTemporarilyNotFoundError, ppa.getSigningKeyData)
         error_view = create_webservice_error_view(error)
-        self.assertEqual(http_client.INTERNAL_SERVER_ERROR, error_view.status)
+        self.assertEqual(http.client.INTERNAL_SERVER_ERROR, error_view.status)
 
 
 class TestCountersAndSummaries(TestCaseWithFactory):
diff --git a/lib/lp/testing/xmlrpc.py b/lib/lp/testing/xmlrpc.py
index 7666680..644a22d 100644
--- a/lib/lp/testing/xmlrpc.py
+++ b/lib/lp/testing/xmlrpc.py
@@ -7,12 +7,10 @@ __all__ = [
     'XMLRPCTestTransport',
     ]
 
+import http.client as http_client
 import io
 
-from six.moves import (
-    http_client,
-    xmlrpc_client,
-    )
+from six.moves import xmlrpc_client
 from zope.security.management import (
     endInteraction,
     queryInteraction,
@@ -28,7 +26,7 @@ from lp.testing.pages import http
 class _FakeSocket(object):
     """Pretend to be a socket that has a makefile method.
 
-    This is used because it is what http_client.HTTPResponse expects.
+    This is used because it is what http.client.HTTPResponse expects.
     """
     def __init__(self, output):
         self._output = output
diff --git a/lib/lp/translations/interfaces/translationimportqueue.py b/lib/lp/translations/interfaces/translationimportqueue.py
index 01f4a25..4a39b01 100644
--- a/lib/lp/translations/interfaces/translationimportqueue.py
+++ b/lib/lp/translations/interfaces/translationimportqueue.py
@@ -2,6 +2,7 @@
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 from datetime import timedelta
+import http.client
 
 from lazr.enum import (
     DBEnumeratedType,
@@ -25,7 +26,6 @@ from lazr.restful.declarations import (
     )
 from lazr.restful.fields import Reference
 from lazr.restful.interface import copy_field
-from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -76,7 +76,7 @@ class TranslationImportQueueConflictError(
     conflicts with existing entries."""
 
 
-@error_status(http_client.UNAUTHORIZED)
+@error_status(http.client.UNAUTHORIZED)
 class UserCannotSetTranslationImportStatus(Unauthorized):
     """User not permitted to change status.