← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:six-httplib into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:six-httplib into launchpad:master.

Commit message:
Import httplib from six.moves.http_client

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

This part of the standard library was rearranged in Python 3.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:six-httplib into launchpad:master.
diff --git a/lib/lp/answers/errors.py b/lib/lp/answers/errors.py
index 259651a..cfd6f47 100644
--- a/lib/lp/answers/errors.py
+++ b/lib/lp/answers/errors.py
@@ -12,12 +12,11 @@ __all__ = [
     'QuestionTargetError',
     ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class AddAnswerContactError(ValueError):
     """The person cannot be an answer contact.
 
@@ -26,12 +25,12 @@ class AddAnswerContactError(ValueError):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class FAQTargetError(ValueError):
     """The target must be an `IFAQTarget`."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class InvalidQuestionStateError(ValueError):
     """Error raised when the question is in an invalid state.
 
@@ -40,21 +39,21 @@ class InvalidQuestionStateError(ValueError):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NotAnswerContactError(ValueError):
     """The person must be an answer contact."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NotMessageOwnerError(ValueError):
     """The person must be the message owner."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NotQuestionOwnerError(ValueError):
     """The person must be the question owner."""
 
 
-@error_status(httplib.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 be253b5..6f1ba18 100644
--- a/lib/lp/answers/interfaces/faq.py
+++ b/lib/lp/answers/interfaces/faq.py
@@ -11,8 +11,6 @@ __all__ = [
     'IFAQSet',
     ]
 
-import httplib
-
 from lazr.restful.declarations import (
     error_status,
     export_as_webservice_entry,
@@ -21,6 +19,7 @@ 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,
@@ -39,7 +38,7 @@ from lp.services.fields import (
     )
 
 
-@error_status(httplib.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 8eb8750..f9df912 100644
--- a/lib/lp/app/errors.py
+++ b/lib/lp/app/errors.py
@@ -17,9 +17,8 @@ __all__ = [
     'UserCannotUnsubscribePerson',
     ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from zope.security.interfaces import (
     ForbiddenAttribute,
     Unauthorized,
@@ -30,12 +29,12 @@ class TranslationUnavailable(Exception):
     """Translation objects are unavailable."""
 
 
-@error_status(httplib.NOT_FOUND)
+@error_status(http_client.NOT_FOUND)
 class NotFoundError(KeyError):
     """Launchpad object not found."""
 
 
-@error_status(httplib.GONE)
+@error_status(http_client.GONE)
 class GoneError(KeyError):
     """Launchpad object is gone."""
 
@@ -73,25 +72,25 @@ class POSTToNonCanonicalURL(UnexpectedFormData):
     """
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotUnsubscribePerson(Unauthorized):
     """User does not have permission to unsubscribe person or team."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class SubscriptionPrivacyViolation(Exception):
     """The subscription would violate privacy policies."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class ServiceUsageForbidden(Exception):
     """The specified ServiceUsage is not allowed."""
 
 
-@error_status(httplib.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(httplib.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 5e6ee51..06bc4c1 100644
--- a/lib/lp/app/tests/test_errors.py
+++ b/lib/lp/app/tests/test_errors.py
@@ -3,7 +3,7 @@
 
 __metaclass__ = type
 
-from httplib import (
+from six.moves.http_client import (
     BAD_REQUEST,
     UNAUTHORIZED,
     )
diff --git a/lib/lp/blueprints/errors.py b/lib/lp/blueprints/errors.py
index df9df4a..dc71017 100644
--- a/lib/lp/blueprints/errors.py
+++ b/lib/lp/blueprints/errors.py
@@ -9,12 +9,11 @@ __all__ = [
     'TargetAlreadyHasSpecification',
     ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 
 
-@error_status(httplib.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 bdc0f9c..ef6dfdc 100644
--- a/lib/lp/blueprints/interfaces/specification.py
+++ b/lib/lp/blueprints/interfaces/specification.py
@@ -14,8 +14,6 @@ __all__ = [
     'ISpecificationView',
     ]
 
-import httplib
-
 from lazr.restful.declarations import (
     call_with,
     collection_default_content,
@@ -37,6 +35,7 @@ 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,
@@ -94,7 +93,7 @@ from lp.services.webapp import canonical_url
 from lp.services.webapp.escaping import structured
 
 
-@error_status(httplib.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 5b0366a..3dfc332 100644
--- a/lib/lp/bugs/browser/bugtarget.py
+++ b/lib/lp/bugs/browser/bugtarget.py
@@ -22,7 +22,6 @@ __all__ = [
 from cStringIO import StringIO
 from datetime import datetime
 from functools import partial
-import httplib
 from operator import itemgetter
 import urllib
 
@@ -30,6 +29,7 @@ from lazr.restful.interface import copy_field
 from lazr.restful.interfaces import IJSONRequestCache
 from pytz import timezone
 from simplejson import dumps
+from six.moves import http_client
 from sqlobject import SQLObjectNotFound
 from zope.browserpage import ViewPageTemplateFile
 from zope.component import getUtility
@@ -902,7 +902,7 @@ class FileBugAdvancedView(LaunchpadView):
         filebug_url = canonical_url(
             self.context, rootsite='bugs', view_name='+filebug')
         self.request.response.redirect(
-            filebug_url, status=httplib.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 02ceee3..4093856 100644
--- a/lib/lp/bugs/errors.py
+++ b/lib/lp/bugs/errors.py
@@ -9,18 +9,17 @@ __all__ = [
     'InvalidSearchParameters',
 ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 
 from lp.app.validators import LaunchpadValidationError
 
 
-@error_status(httplib.EXPECTATION_FAILED)
+@error_status(http_client.EXPECTATION_FAILED)
 class InvalidDuplicateValue(LaunchpadValidationError):
     """A bug cannot be set as the duplicate of another."""
 
 
-@error_status(httplib.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 688c03a..ffdb35e 100644
--- a/lib/lp/bugs/externalbugtracker/bugzilla.py
+++ b/lib/lp/bugs/externalbugtracker/bugzilla.py
@@ -12,7 +12,6 @@ __all__ = [
     ]
 
 from email.utils import parseaddr
-from httplib import BadStatusLine
 import re
 import string
 import xml.parsers.expat
@@ -22,6 +21,7 @@ from defusedxml import minidom
 import pytz
 import requests
 import six
+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 e2c462b..038a532 100644
--- a/lib/lp/bugs/externalbugtracker/github.py
+++ b/lib/lp/bugs/externalbugtracker/github.py
@@ -12,13 +12,13 @@ __all__ = [
     ]
 
 from contextlib import contextmanager
-import httplib
 import time
 from urllib import urlencode
 from urlparse import urlunsplit
 
 import pytz
 import requests
+from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import Interface
 
@@ -256,7 +256,8 @@ class GitHub(ExternalBugTracker):
                 response = self._getPage(page, last_accessed=last_accessed)
             except BugTrackerConnectError as e:
                 if (e.error.response is not None and
-                        e.error.response.status_code == httplib.NOT_MODIFIED):
+                    e.error.response.status_code ==
+                        http_client.NOT_MODIFIED):
                     return
                 else:
                     raise
diff --git a/lib/lp/bugs/externalbugtracker/gitlab.py b/lib/lp/bugs/externalbugtracker/gitlab.py
index 357aa60..ed5187b 100644
--- a/lib/lp/bugs/externalbugtracker/gitlab.py
+++ b/lib/lp/bugs/externalbugtracker/gitlab.py
@@ -9,9 +9,8 @@ __all__ = [
     'GitLab',
     ]
 
-import httplib
-
 import pytz
+from six.moves import http_client
 from six.moves.urllib.parse import (
     quote,
     quote_plus,
@@ -160,7 +159,8 @@ class GitLab(ExternalBugTracker):
                 response = self._getPage(page, last_accessed=last_accessed)
             except BugTrackerConnectError as e:
                 if (e.error.response is not None and
-                        e.error.response.status_code == httplib.NOT_MODIFIED):
+                    e.error.response.status_code ==
+                        http_client.NOT_MODIFIED):
                     return
                 else:
                     raise
diff --git a/lib/lp/bugs/interfaces/bugnomination.py b/lib/lp/bugs/interfaces/bugnomination.py
index 3957c9d..7bb6618 100644
--- a/lib/lp/bugs/interfaces/bugnomination.py
+++ b/lib/lp/bugs/interfaces/bugnomination.py
@@ -14,8 +14,6 @@ __all__ = [
     'BugNominationStatus',
     'NominationSeriesObsoleteError']
 
-import httplib
-
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -33,6 +31,7 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -55,17 +54,17 @@ from lp.registry.interfaces.role import IHasOwner
 from lp.services.fields import PublicPersonChoice
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NominationError(Exception):
     """The bug cannot be nominated for this release."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NominationSeriesObsoleteError(Exception):
     """A bug cannot be nominated for an obsolete series."""
 
 
-@error_status(httplib.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 f3e27dd..387c7f1 100644
--- a/lib/lp/bugs/interfaces/bugtask.py
+++ b/lib/lp/bugs/interfaces/bugtask.py
@@ -34,8 +34,6 @@ __all__ = [
     'valid_remote_bug_url',
     ]
 
-import httplib
-
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -62,6 +60,7 @@ 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,
@@ -323,7 +322,7 @@ BUG_SUPERVISOR_BUGTASK_STATUSES = (
     BugTaskStatus.TRIAGED)
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotDeleteBugtask(Exception):
     """The bugtask cannot be deleted.
 
@@ -332,7 +331,7 @@ class CannotDeleteBugtask(Exception):
     """
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotEditBugTaskStatus(Unauthorized):
     """User not permitted to change status.
 
@@ -341,7 +340,7 @@ class UserCannotEditBugTaskStatus(Unauthorized):
     """
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotEditBugTaskImportance(Unauthorized):
     """User not permitted to change importance.
 
@@ -350,7 +349,7 @@ class UserCannotEditBugTaskImportance(Unauthorized):
     """
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotEditBugTaskMilestone(Unauthorized):
     """User not permitted to change milestone.
 
@@ -359,7 +358,7 @@ class UserCannotEditBugTaskMilestone(Unauthorized):
     """
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotEditBugTaskAssignee(Unauthorized):
     """User not permitted to change bugtask assignees.
 
@@ -368,7 +367,7 @@ class UserCannotEditBugTaskAssignee(Unauthorized):
     """
 
 
-@error_status(httplib.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 48cd380..fb9a950 100644
--- a/lib/lp/bugs/interfaces/bugtasksearch.py
+++ b/lib/lp/bugs/interfaces/bugtasksearch.py
@@ -21,7 +21,6 @@ __all__ = [
     ]
 
 import collections
-import httplib
 
 from lazr.enum import (
     EnumeratedType,
@@ -29,6 +28,7 @@ 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,
@@ -59,7 +59,7 @@ from lp.services.searchbuilder import (
 from lp.soyuz.interfaces.component import IComponent
 
 
-@error_status(httplib.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 6fe224f..712a3c6 100644
--- a/lib/lp/bugs/model/bugsubscriptionfilter.py
+++ b/lib/lp/bugs/model/bugsubscriptionfilter.py
@@ -11,11 +11,11 @@ __all__ = [
     'BugSubscriptionFilterTag',
     ]
 
-import httplib
 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,
@@ -51,7 +51,7 @@ from lp.services.database.sqlbase import convert_storm_clause_to_string
 from lp.services.database.stormbase import StormBase
 
 
-@error_status(httplib.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 3f420c3..b1d8dfb 100644
--- a/lib/lp/bugs/tests/test_errors.py
+++ b/lib/lp/bugs/tests/test_errors.py
@@ -7,7 +7,7 @@
 __metaclass__ = type
 
 
-from httplib import EXPECTATION_FAILED
+from six.moves.http_client import EXPECTATION_FAILED
 
 from lp.bugs.errors import InvalidDuplicateValue
 from lp.testing import TestCase
diff --git a/lib/lp/code/errors.py b/lib/lp/code/errors.py
index c68da65..85de140 100644
--- a/lib/lp/code/errors.py
+++ b/lib/lp/code/errors.py
@@ -64,11 +64,10 @@ __all__ = [
     'WrongBranchMergeProposal',
 ]
 
-import httplib
-
 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,
@@ -76,14 +75,14 @@ from lp.app.errors import (
     )
 
 # Annotate the RecipeParseError's with a 400 webservice status.
-error_status(httplib.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(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class BadStateTransition(Exception):
     """The user requested a state transition that is not possible."""
 
@@ -92,7 +91,7 @@ class BranchCreationException(Exception):
     """Base class for branch creation exceptions."""
 
 
-@error_status(httplib.CONFLICT)
+@error_status(http_client.CONFLICT)
 class BranchExists(BranchCreationException):
     """Raised when creating a branch that already exists."""
 
@@ -128,7 +127,7 @@ class BranchTargetError(Exception):
     """Raised when there is an error determining a branch target."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotDeleteBranch(Exception):
     """The branch cannot be deleted at this time."""
 
@@ -141,7 +140,7 @@ class BranchCreationForbidden(BranchCreationException):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class BranchCreatorNotMemberOfOwnerTeam(BranchCreationException):
     """Branch creator is not a member of the owner team.
 
@@ -150,7 +149,7 @@ class BranchCreatorNotMemberOfOwnerTeam(BranchCreationException):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class BranchCreatorNotOwner(BranchCreationException):
     """A user cannot create a branch belonging to another user.
 
@@ -230,7 +229,7 @@ class ClaimReviewFailed(Exception):
     """The user cannot claim the pending review."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class InvalidBranchMergeProposal(Exception):
     """Raised during the creation of a new branch merge proposal.
 
@@ -238,7 +237,7 @@ class InvalidBranchMergeProposal(Exception):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class BranchMergeProposalExists(InvalidBranchMergeProposal):
     """Raised if there is already a matching BranchMergeProposal."""
 
@@ -301,7 +300,7 @@ class StaleLastMirrored(Exception):
             (db_branch.last_mirrored_id, self.info['last_revision_id']))
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class PrivateBranchRecipe(Exception):
 
     def __init__(self, branch):
@@ -311,7 +310,7 @@ class PrivateBranchRecipe(Exception):
         Exception.__init__(self, message)
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class PrivateGitRepositoryRecipe(Exception):
 
     def __init__(self, repository):
@@ -383,7 +382,7 @@ class GitRepositoryCreationException(Exception):
     """Base class for Git repository creation exceptions."""
 
 
-@error_status(httplib.CONFLICT)
+@error_status(http_client.CONFLICT)
 class GitRepositoryExists(GitRepositoryCreationException):
     """Raised when creating a Git repository that already exists."""
 
@@ -399,7 +398,7 @@ class GitRepositoryExists(GitRepositoryCreationException):
         GitRepositoryCreationException.__init__(self, message)
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotDeleteGitRepository(Exception):
     """The Git repository cannot be deleted at this time."""
 
@@ -413,7 +412,7 @@ class GitRepositoryCreationForbidden(GitRepositoryCreationException):
 
 
 @six.python_2_unicode_compatible
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class GitRepositoryCreatorNotMemberOfOwnerTeam(GitRepositoryCreationException):
     """Git repository creator is not a member of the owner team.
 
@@ -432,7 +431,7 @@ class GitRepositoryCreatorNotMemberOfOwnerTeam(GitRepositoryCreationException):
 
 
 @six.python_2_unicode_compatible
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class GitRepositoryCreatorNotOwner(GitRepositoryCreationException):
     """A user cannot create a Git repository belonging to another user.
 
@@ -519,7 +518,7 @@ class NoSuchGitReference(NotFoundError):
         return self.message
 
 
-@error_status(httplib.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."""
@@ -544,7 +543,7 @@ class GitDefaultConflict(Exception):
         Exception.__init__(self, message)
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class CannotModifyNonHostedGitRepository(Exception):
     """Raised when trying to modify a non-hosted Git repository."""
 
@@ -554,7 +553,7 @@ class CannotModifyNonHostedGitRepository(Exception):
             repository.display_name)
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CodeImportNotInReviewedState(Exception):
     """Raised when the user requests an import of a non-automatic import."""
 
@@ -567,12 +566,12 @@ class CodeImportAlreadyRequested(Exception):
         self.requesting_user = requesting_user
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CodeImportAlreadyRunning(Exception):
     """Raised when the user requests an import that is already running."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CodeImportInvalidTargetType(Exception):
     """Raised for code imports with an invalid target for their type."""
 
@@ -582,7 +581,7 @@ class CodeImportInvalidTargetType(Exception):
             (target.__class__.__name__, target_rcs_type))
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class TooNewRecipeFormat(Exception):
     """The format of the recipe supplied was too new."""
 
@@ -592,7 +591,7 @@ class TooNewRecipeFormat(Exception):
         self.newest_supported = newest_supported
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class RecipeBuildException(Exception):
 
     def __init__(self, recipe, distroseries, template):
@@ -620,6 +619,6 @@ class BuildNotAllowedForDistro(RecipeBuildException):
             'A build against this distro is not allowed.')
 
 
-@error_status(httplib.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 29d5fdf..f0e9393 100644
--- a/lib/lp/code/interfaces/branch.py
+++ b/lib/lp/code/interfaces/branch.py
@@ -22,7 +22,6 @@ __all__ = [
     'WrongNumberOfReviewTypeArguments',
     ]
 
-import httplib
 import re
 
 from lazr.restful.declarations import (
@@ -51,6 +50,7 @@ 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,
@@ -114,7 +114,7 @@ DEFAULT_BRANCH_STATUS_IN_LISTING = (
     BranchLifecycleStatus.MATURE)
 
 
-@error_status(httplib.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 1819e95..8abc1e5 100644
--- a/lib/lp/codehosting/puller/tests/test_errors.py
+++ b/lib/lp/codehosting/puller/tests/test_errors.py
@@ -5,7 +5,6 @@
 
 __metaclass__ = type
 
-import httplib
 import os
 import socket
 import tempfile
@@ -23,6 +22,7 @@ from breezy.url_policy_open import (
     BranchReferenceForbidden,
     )
 from lazr.uri import InvalidURIError
+from six.moves import http_client
 
 from lp.code.enums import BranchType
 from lp.codehosting.puller.worker import (
@@ -142,7 +142,7 @@ class TestErrorCatching(TestCase):
         # error message.
         msg = self.getMirrorFailureForException(
             urllib2.HTTPError(
-                'http://something', httplib.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 d0ed4ca..a15ee1a 100644
--- a/lib/lp/codehosting/puller/worker.py
+++ b/lib/lp/codehosting/puller/worker.py
@@ -3,7 +3,6 @@
 
 __metaclass__ = type
 
-import httplib
 import socket
 import sys
 import urllib2
@@ -41,6 +40,7 @@ from lazr.uri import (
     InvalidURIError,
     URI,
     )
+from six.moves import http_client
 
 from lp.code.bzr import (
     BranchFormat,
@@ -389,7 +389,7 @@ class PullerWorker:
         #
         except urllib2.HTTPError as e:
             msg = str(e)
-            if int(e.code) == httplib.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/hardwaredb/interfaces/hwdb.py b/lib/lp/hardwaredb/interfaces/hwdb.py
index abb9663..082c742 100644
--- a/lib/lp/hardwaredb/interfaces/hwdb.py
+++ b/lib/lp/hardwaredb/interfaces/hwdb.py
@@ -40,8 +40,6 @@ __all__ = [
     'ParameterError',
     ]
 
-import httplib
-
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -64,6 +62,7 @@ from lazr.restful.fields import (
     Reference,
     )
 from lazr.restful.interface import copy_field
+from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -1690,11 +1689,11 @@ class IHWDBApplication(ILaunchpadApplication):
         """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class IllegalQuery(Exception):
     """Exception raised when trying to run an illegal submissions query."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class ParameterError(Exception):
     """Exception raised when a method parameter does not match a constrint."""
diff --git a/lib/lp/registry/errors.py b/lib/lp/registry/errors.py
index 077d3ad..9b6c81e 100644
--- a/lib/lp/registry/errors.py
+++ b/lib/lp/registry/errors.py
@@ -35,26 +35,25 @@ __all__ = [
     'UserCannotSubscribePerson',
     ]
 
-import httplib
-
 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(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class PrivatePersonLinkageError(ValueError):
     """An attempt was made to link a private person/team to something."""
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class InclusiveTeamLinkageError(ValueError):
     """An attempt was made to link an open team to something."""
 
 
-@error_status(httplib.CONFLICT)
+@error_status(http_client.CONFLICT)
 class NameAlreadyTaken(Exception):
     """The name given for a person is already in use by other person."""
 
@@ -63,17 +62,17 @@ class InvalidName(Exception):
     """The name given for a person is not valid."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NotPlaceholderAccount(Exception):
     """A non-placeholder account already exists for that OpenID identifier."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NoSuchAccount(Exception):
     """No account exists for the specified openid identifier."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class InvalidFilename(Exception):
     """An invalid filename was used as an attachment filename."""
 
@@ -83,7 +82,7 @@ class NoSuchDistroSeries(NameLookupFailed):
     _message_prefix = "No such distribution series"
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotChangeMembershipSilently(Unauthorized):
     """User not permitted to change membership status silently.
 
@@ -92,7 +91,7 @@ class UserCannotChangeMembershipSilently(Unauthorized):
     """
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class CommercialSubscribersOnly(Unauthorized):
     """Feature is only available to current commercial subscribers.
 
@@ -115,7 +114,7 @@ class NoSuchOCIProjectName(NameLookupFailed):
     _message_prefix = "No such OCI Project"
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotTransitionToCountryMirror(Exception):
     """Root exception for transitions to country mirrors."""
 
@@ -152,7 +151,7 @@ class MirrorNotProbed(CannotTransitionToCountryMirror):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class DeleteSubscriptionError(Exception):
     """Delete Subscription Error.
 
@@ -160,12 +159,12 @@ class DeleteSubscriptionError(Exception):
     structural subscription."""
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotSubscribePerson(Exception):
     """User does not have permission to subscribe the person or team."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class DistroSeriesDifferenceError(Exception):
     """Raised when package diffs cannot be created for a difference."""
 
@@ -177,7 +176,7 @@ class NotADerivedSeriesError(Exception):
     non-derived series - that is, a distroseries with a null Parent."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class TeamMembershipTransitionError(ValueError):
     """Indicates something has gone wrong with the transtiion.
 
@@ -186,7 +185,7 @@ class TeamMembershipTransitionError(ValueError):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class TeamMembershipPolicyError(ConstraintNotSatisfied):
     """The team cannot have the specified TeamMembershipPolicy.
 
@@ -210,12 +209,12 @@ class TeamMembershipPolicyError(ConstraintNotSatisfied):
         return self.message
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class JoinNotAllowed(Exception):
     """User is not allowed to join a given team."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class PPACreationError(Exception):
     """Raised when there is an issue creating a new PPA."""
 
@@ -224,12 +223,12 @@ class CannotDeleteCommercialSubscription(Exception):
     """Raised when a commercial subscription cannot be deleted."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotChangeInformationType(Exception):
     """The information type cannot be changed."""
 
 
-@error_status(httplib.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/distroseries.py b/lib/lp/registry/interfaces/distroseries.py
index c35f1a6..19233a3 100644
--- a/lib/lp/registry/interfaces/distroseries.py
+++ b/lib/lp/registry/interfaces/distroseries.py
@@ -14,8 +14,6 @@ __all__ = [
     'IDistroSeriesSet',
     ]
 
-import httplib
-
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -37,6 +35,7 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
+from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import (
     Attribute,
@@ -1069,7 +1068,7 @@ class IDistroSeriesSet(Interface):
         """
 
 
-@error_status(httplib.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/person.py b/lib/lp/registry/interfaces/person.py
index de0721a..fd501e9 100644
--- a/lib/lp/registry/interfaces/person.py
+++ b/lib/lp/registry/interfaces/person.py
@@ -38,8 +38,6 @@ __all__ = [
     'validate_membership_policy',
     ]
 
-import httplib
-
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -70,6 +68,7 @@ from lazr.restful.fields import (
     Reference,
     )
 from lazr.restful.interface import copy_field
+from six.moves import http_client
 from zope.component import getUtility
 from zope.formlib.form import NoInputData
 from zope.interface import (
@@ -2670,12 +2669,12 @@ class ICanonicalSSOAPI(Interface):
         """Get the details of an LP person based on an OpenID identifier."""
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class ImmutableVisibilityError(Exception):
     """A change in team membership visibility is not allowed."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NoAccountError(Exception):
     """The person has no account."""
 
diff --git a/lib/lp/registry/interfaces/ssh.py b/lib/lp/registry/interfaces/ssh.py
index 2852253..7d78030 100644
--- a/lib/lp/registry/interfaces/ssh.py
+++ b/lib/lp/registry/interfaces/ssh.py
@@ -13,8 +13,6 @@ __all__ = [
     'SSHKeyType',
     ]
 
-import httplib
-
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -25,6 +23,7 @@ from lazr.restful.declarations import (
     exported,
     )
 import six
+from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Choice,
@@ -128,7 +127,7 @@ class ISSHKeySet(Interface):
         """
 
 
-@error_status(httplib.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 2c66544..aa80a20 100644
--- a/lib/lp/registry/model/milestone.py
+++ b/lib/lp/registry/model/milestone.py
@@ -14,10 +14,10 @@ __all__ = [
     ]
 
 import datetime
-import httplib
 from operator import itemgetter
 
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from sqlobject import (
     AND,
     BoolCol,
@@ -125,7 +125,7 @@ class HasMilestonesMixin:
     milestones = property(_get_milestones)
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class MultipleProductReleases(Exception):
     """Raised when a second ProductRelease is created for a milestone."""
 
@@ -133,7 +133,7 @@ class MultipleProductReleases(Exception):
         super(MultipleProductReleases, self).__init__(msg)
 
 
-@error_status(httplib.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 a68b25b..a99d846 100644
--- a/lib/lp/registry/model/product.py
+++ b/lib/lp/registry/model/product.py
@@ -13,7 +13,6 @@ __all__ = [
 
 
 import datetime
-import httplib
 import itertools
 import operator
 
@@ -21,6 +20,7 @@ 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 sqlobject import (
     BoolCol,
     ForeignKey,
@@ -256,7 +256,7 @@ def get_license_status(license_approved, project_reviewed, licenses):
         return LicenseStatus.OPEN_SOURCE
 
 
-@error_status(httplib.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 ab25488..1aa5ca3 100644
--- a/lib/lp/registry/scripts/distributionmirror_prober.py
+++ b/lib/lp/registry/scripts/distributionmirror_prober.py
@@ -7,7 +7,6 @@ __all__ = [
     ]
 
 from datetime import datetime
-import httplib
 import itertools
 import logging
 import os.path
@@ -16,6 +15,7 @@ import urllib
 import urlparse
 
 import requests
+from six.moves import http_client
 from twisted.internet import (
     defer,
     protocol,
@@ -145,7 +145,7 @@ class ProberProtocol(HTTPClient):
         # According to http://lists.debian.org/deity/2001/10/msg00046.html,
         # apt intentionally handles only '200 OK' responses, so we do the
         # same here.
-        if status == str(httplib.OK):
+        if status == str(http_client.OK):
             self.factory.succeeded(status)
         else:
             self.factory.failed(Failure(BadResponseCode(status)))
@@ -164,7 +164,8 @@ class RedirectAwareProberProtocol(ProberProtocol):
 
     # The different redirect statuses that I handle.
     handled_redirect_statuses = (
-        httplib.MOVED_PERMANENTLY, httplib.FOUND, httplib.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 b9ccc08..39228d2 100644
--- a/lib/lp/registry/tests/test_distributionmirror_prober.py
+++ b/lib/lp/registry/tests/test_distributionmirror_prober.py
@@ -7,13 +7,13 @@ __metaclass__ = type
 
 
 from datetime import datetime
-import httplib
 import logging
 import os
 from StringIO import StringIO
 
 from lazr.uri import URI
 import responses
+from six.moves import http_client
 from sqlobject import SQLObjectNotFound
 from testtools.matchers import (
     ContainsDict,
@@ -210,7 +210,7 @@ class TestProberProtocolAndFactory(TestCase):
             self.assertTrue(prober.redirection_count == 1)
             new_url = 'http://localhost:%s/valid-mirror/file' % self.port
             self.assertTrue(prober.url == new_url)
-            self.assertTrue(result == str(httplib.OK))
+            self.assertTrue(result == str(http_client.OK))
 
         return deferred.addCallback(got_result)
 
@@ -231,7 +231,7 @@ class TestProberProtocolAndFactory(TestCase):
 
         def got_result(result):
             self.assertTrue(
-                result == str(httplib.OK),
+                result == str(http_client.OK),
                 "Expected a '200' status but got '%s'" % result)
 
         return d.addCallback(got_result)
@@ -708,7 +708,8 @@ class TestMirrorCDImageProberCallbacks(TestCaseWithFactory):
 
     def test_mirrorcdimageseries_creation_and_deletion_some_404s(self):
         not_all_success = [
-            (defer.FAILURE, Failure(BadResponseCode(str(httplib.NOT_FOUND)))),
+            (defer.FAILURE,
+             Failure(BadResponseCode(str(http_client.NOT_FOUND)))),
             (defer.SUCCESS, '200')]
         callbacks = self.makeMirrorProberCallbacks()
         all_success = [(defer.SUCCESS, '200'), (defer.SUCCESS, '200')]
@@ -737,7 +738,7 @@ class TestMirrorCDImageProberCallbacks(TestCaseWithFactory):
                 RedirectToDifferentFile,
                 UnknownURLSchemeAfterRedirect,
                 ]))
-        exceptions = [BadResponseCode(str(httplib.NOT_FOUND)),
+        exceptions = [BadResponseCode(str(http_client.NOT_FOUND)),
                       ProberTimeout('http://localhost/', 5),
                       ConnectionSkipped(),
                       RedirectToDifferentFile('/foo', '/bar'),
@@ -794,7 +795,8 @@ class TestArchiveMirrorProberCallbacks(TestCaseWithFactory):
             self.fail("A timeout shouldn't be propagated. Got %s" % e)
         try:
             callbacks.deleteMirrorSeries(
-                Failure(BadResponseCode(str(httplib.INTERNAL_SERVER_ERROR))))
+                Failure(BadResponseCode(
+                    str(http_client.INTERNAL_SERVER_ERROR))))
         except Exception as e:
             self.fail(
                 "A bad response code shouldn't be propagated. Got %s" % e)
@@ -825,7 +827,7 @@ class TestArchiveMirrorProberCallbacks(TestCaseWithFactory):
     def test_mirrorseries_creation_and_deletion(self):
         callbacks = self.makeMirrorProberCallbacks()
         mirror_distro_series_source = callbacks.ensureMirrorSeries(
-             str(httplib.OK))
+             str(http_client.OK))
         self.assertIsNot(
             mirror_distro_series_source, None,
             "If the prober gets a 200 Okay status, a new "
@@ -833,7 +835,7 @@ class TestArchiveMirrorProberCallbacks(TestCaseWithFactory):
             "created.")
 
         callbacks.deleteMirrorSeries(
-            Failure(BadResponseCode(str(httplib.NOT_FOUND))))
+            Failure(BadResponseCode(str(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 02b037f..bb7a327 100644
--- a/lib/lp/registry/tests/test_errors.py
+++ b/lib/lp/registry/tests/test_errors.py
@@ -7,7 +7,7 @@
 __metaclass__ = type
 
 
-from httplib import (
+from six.moves.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 b07a016..345213f 100644
--- a/lib/lp/registry/tests/test_team_webservice.py
+++ b/lib/lp/registry/tests/test_team_webservice.py
@@ -3,12 +3,11 @@
 
 __metaclass__ = type
 
-import httplib
-
 from lazr.restfulclient.errors import (
     HTTPError,
     Unauthorized,
     )
+from six.moves import http_client
 import transaction
 
 from lp.app.enums import InformationType
@@ -49,7 +48,7 @@ class TestTeamJoining(TestCaseWithFactory):
             HTTPError,
             person.join,
             team='test-team')
-        self.assertEqual(httplib.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 4daa8e6..c81ca75 100644
--- a/lib/lp/services/gpg/handler.py
+++ b/lib/lp/services/gpg/handler.py
@@ -12,7 +12,6 @@ __all__ = [
 
 import atexit
 from contextlib import contextmanager
-import httplib
 import os
 import shutil
 import socket
@@ -25,6 +24,7 @@ import urllib
 import gpgme
 from lazr.restful.utils import get_current_browser_request
 import requests
+from six.moves import http_client
 from zope.interface import implementer
 from zope.security.proxy import removeSecurityProxy
 
@@ -466,7 +466,7 @@ class GPGHandler:
         keyserver_http_url = '%s:%s' % (
             config.gpghandler.host, config.gpghandler.port)
 
-        conn = httplib.HTTPConnection(keyserver_http_url)
+        conn = http_client.HTTPConnection(keyserver_http_url)
         params = urllib.urlencode({'keytext': content})
         headers = {
             "Content-type": "application/x-www-form-urlencoded",
@@ -480,7 +480,7 @@ class GPGHandler:
                 'Could not reach keyserver at http://%s %s' % (
                     keyserver_http_url, str(err)))
 
-        assert conn.getresponse().status == httplib.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 3021b24..462c279 100644
--- a/lib/lp/services/gpg/interfaces.py
+++ b/lib/lp/services/gpg/interfaces.py
@@ -23,7 +23,6 @@ __all__ = [
     'valid_keyid',
     ]
 
-import httplib
 import os.path
 import re
 
@@ -32,6 +31,7 @@ from lazr.enum import (
     DBItem,
     )
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -139,7 +139,7 @@ class GPGKeyNotFoundError(Exception):
         super(GPGKeyNotFoundError, self).__init__(message)
 
 
-@error_status(httplib.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.
 
@@ -154,7 +154,7 @@ class GPGKeyTemporarilyNotFoundError(GPGKeyNotFoundError):
             fingerprint, message)
 
 
-@error_status(httplib.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 5f580cf..e355e43 100644
--- a/lib/lp/services/identity/interfaces/account.py
+++ b/lib/lp/services/identity/interfaces/account.py
@@ -18,13 +18,12 @@ __all__ = [
     'INACTIVE_ACCOUNT_STATUSES',
     ]
 
-import httplib
-
 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,
@@ -42,7 +41,7 @@ from lp.app.validators import LaunchpadValidationError
 from lp.services.fields import StrippedTextLine
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class AccountSuspendedError(Exception):
     """The account being accessed has been suspended."""
 
diff --git a/lib/lp/services/identity/interfaces/emailaddress.py b/lib/lp/services/identity/interfaces/emailaddress.py
index e0f27c5..3af3a22 100644
--- a/lib/lp/services/identity/interfaces/emailaddress.py
+++ b/lib/lp/services/identity/interfaces/emailaddress.py
@@ -12,8 +12,6 @@ __all__ = [
     'InvalidEmailAddress',
     'VALID_EMAIL_STATUSES']
 
-import httplib
-
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -24,6 +22,7 @@ from lazr.restful.declarations import (
     exported,
     )
 from lazr.restful.fields import Reference
+from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Choice,
@@ -39,7 +38,7 @@ class InvalidEmailAddress(Exception):
     """The email address is not valid."""
 
 
-@error_status(httplib.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 edb1d72..687e8b8 100644
--- a/lib/lp/services/librarian/client.py
+++ b/lib/lp/services/librarian/client.py
@@ -14,7 +14,6 @@ __all__ = [
 
 
 import hashlib
-import httplib
 from select import select
 import socket
 from socket import (
@@ -33,6 +32,7 @@ from urlparse import (
 
 from lazr.restful.utils import get_current_browser_request
 import six
+from six.moves import http_client
 from storm.store import Store
 from zope.interface import implementer
 
@@ -316,7 +316,7 @@ class _File:
                 # from a non-chunked-transfer-coding resource.  Check this
                 # manually.
                 if not s and chunksize != 0 and self.length:
-                    raise httplib.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 75320ee..7ba3905 100644
--- a/lib/lp/services/librarian/interfaces/client.py
+++ b/lib/lp/services/librarian/interfaces/client.py
@@ -13,10 +13,10 @@ __all__ = [
     'UploadFailed',
     ]
 
-import httplib
 import signal
 
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from zope.interface import Interface
 
 
@@ -36,7 +36,7 @@ class DownloadFailed(LibrarianFailure):
     pass
 
 
-@error_status(httplib.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 a30a9bc..4f061ce 100644
--- a/lib/lp/services/librarian/tests/test_client.py
+++ b/lib/lp/services/librarian/tests/test_client.py
@@ -3,7 +3,6 @@
 
 from cStringIO import StringIO
 import hashlib
-import httplib
 import os
 import re
 import textwrap
@@ -18,6 +17,7 @@ from fixtures import (
     EnvironmentVariable,
     TempDir,
     )
+from six.moves import http_client
 import transaction
 
 from lp.services.config import config
@@ -149,7 +149,7 @@ class LibrarianFileWrapperTestCase(TestCase):
     def test_unbounded_read_incorrect_length(self):
         file = self.makeFile(extra_content_length=1)
         self.assertEqual(b"abcdef", file.read())
-        self.assertRaises(httplib.IncompleteRead, file.read)
+        self.assertRaises(http_client.IncompleteRead, file.read)
 
     def test_bounded_read_correct_length(self):
         file = self.makeFile()
@@ -161,7 +161,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(httplib.IncompleteRead, file.read, chunksize=4)
+        self.assertRaises(http_client.IncompleteRead, file.read, chunksize=4)
 
 
 class LibrarianClientTestCase(unittest.TestCase):
@@ -422,4 +422,4 @@ class TestWebServiceErrors(unittest.TestCase):
 
     def test_LibrarianServerError_timeout(self):
         error_view = create_webservice_error_view(LibrarianServerError())
-        self.assertEqual(httplib.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 b2136ab..3ba366a 100644
--- a/lib/lp/services/librarianserver/tests/test_web.py
+++ b/lib/lp/services/librarianserver/tests/test_web.py
@@ -6,7 +6,6 @@ __metaclass__ = type
 from datetime import datetime
 from gzip import GzipFile
 import hashlib
-import httplib
 from io import BytesIO
 import os
 import unittest
@@ -15,6 +14,7 @@ from urlparse import urlparse
 from lazr.uri import URI
 import pytz
 import requests
+from six.moves import http_client
 from storm.expr import SQL
 from testtools.matchers import EndsWith
 import transaction
@@ -360,7 +360,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 = httplib.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 a50e034..48e5c41 100644
--- a/lib/lp/services/oauth/interfaces.py
+++ b/lib/lp/services/oauth/interfaces.py
@@ -17,9 +17,8 @@ __all__ = [
     'TokenException',
     ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -268,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(httplib.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 b115eb9..bd75959 100644
--- a/lib/lp/services/tests/test_xmlrpc.py
+++ b/lib/lp/services/tests/test_xmlrpc.py
@@ -5,7 +5,7 @@
 
 __metaclass__ = type
 
-import httplib
+from six.moves import http_client
 
 from lp.services.xmlrpc import Transport
 from lp.testing import TestCase
@@ -19,7 +19,7 @@ class TestTransport(TestCase):
 
     def test_default_initialization(self):
         transport = Transport()
-        conn = httplib.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 5712962..dfb3067 100644
--- a/lib/lp/services/webapp/error.py
+++ b/lib/lp/services/webapp/error.py
@@ -13,10 +13,10 @@ __all__ = [
     ]
 
 
-import httplib
 import sys
 import traceback
 
+from six.moves import http_client
 from zope.browser.interfaces import ISystemErrorView
 from zope.browserpage import ViewPageTemplateFile
 from zope.component import getUtility
@@ -45,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 = httplib.INTERNAL_SERVER_ERROR
+    response_code = http_client.INTERNAL_SERVER_ERROR
 
     show_tracebacks = False
     debugging = False
@@ -184,7 +184,7 @@ class NotFoundView(SystemErrorView):
 
     page_title = 'Error: Page not found'
 
-    response_code = httplib.NOT_FOUND
+    response_code = http_client.NOT_FOUND
 
     def __call__(self):
         return self.index()
@@ -215,14 +215,14 @@ class GoneView(NotFoundView):
 
     page_title = 'Error: Page gone'
 
-    response_code = httplib.GONE
+    response_code = http_client.GONE
 
 
 class RequestExpiredView(SystemErrorView):
 
     page_title = 'Error: Timeout'
 
-    response_code = httplib.SERVICE_UNAVAILABLE
+    response_code = http_client.SERVICE_UNAVAILABLE
 
     def __init__(self, context, request):
         SystemErrorView.__init__(self, context, request)
@@ -237,7 +237,7 @@ class InvalidBatchSizeView(SystemErrorView):
 
     page_title = "Error: Invalid Batch Size"
 
-    response_code = httplib.BAD_REQUEST
+    response_code = http_client.BAD_REQUEST
 
     def isSystemError(self):
         """We don't need to log these errors in the SiteLog."""
@@ -255,7 +255,7 @@ class TranslationUnavailableView(SystemErrorView):
 
     page_title = 'Error: Translation page is not available'
 
-    response_code = httplib.SERVICE_UNAVAILABLE
+    response_code = http_client.SERVICE_UNAVAILABLE
 
     def __call__(self):
         return self.index()
@@ -264,12 +264,12 @@ class TranslationUnavailableView(SystemErrorView):
 class NoReferrerErrorView(SystemErrorView):
     """View rendered when a POST request does not include a REFERER header."""
 
-    response_code = httplib.FORBIDDEN
+    response_code = http_client.FORBIDDEN
 
 
 class OpenIdDiscoveryFailureView(SystemErrorView):
 
-    response_code = httplib.SERVICE_UNAVAILABLE
+    response_code = http_client.SERVICE_UNAVAILABLE
 
     def isSystemError(self):
         """We don't need to log these errors in the SiteLog."""
@@ -278,7 +278,7 @@ class OpenIdDiscoveryFailureView(SystemErrorView):
 
 class DisconnectionErrorView(SystemErrorView):
 
-    response_code = httplib.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 843e191..fccb857 100644
--- a/lib/lp/services/webapp/publisher.py
+++ b/lib/lp/services/webapp/publisher.py
@@ -27,7 +27,6 @@ __all__ = [
     ]
 
 from cgi import FieldStorage
-import httplib
 import re
 from wsgiref.headers import Headers
 
@@ -40,6 +39,7 @@ from lazr.restful.interfaces import IJSONRequestCache
 from lazr.restful.tales import WebLayerAPI
 from lazr.restful.utils import get_current_browser_request
 import simplejson
+from six.moves import http_client
 from zope.app.publisher.xmlrpc import IMethodPublisher
 from zope.component import (
     getUtility,
@@ -94,7 +94,7 @@ from lp.services.webapp.vhosts import allvhosts
 
 # Monkeypatch NotFound to always avoid generating OOPS
 # from NotFound in web service calls.
-error_status(httplib.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 4485f09..0c7359f 100644
--- a/lib/lp/services/webapp/tests/test_error.py
+++ b/lib/lp/services/webapp/tests/test_error.py
@@ -4,13 +4,13 @@
 """Test error views."""
 
 
-import httplib
 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 +111,7 @@ class TestDatabaseErrorViews(TestCase):
                 browser.open(url)
                 return
             except HTTPError as e:
-                if e.code != httplib.SERVICE_UNAVAILABLE:
+                if e.code != http_client.SERVICE_UNAVAILABLE:
                     raise
             time.sleep(1)
         else:
@@ -246,7 +246,7 @@ class TestDatabaseErrorViews(TestCase):
         browser.raiseHttpErrors = False
         browser.open(url)
         self.assertEqual(
-            httplib.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 7067684..20e4b52 100644
--- a/lib/lp/services/webapp/tests/test_errorlog.py
+++ b/lib/lp/services/webapp/tests/test_errorlog.py
@@ -5,7 +5,6 @@
 
 __metaclass__ = type
 
-import httplib
 import sys
 from textwrap import dedent
 import traceback
@@ -15,6 +14,7 @@ from lazr.batchnavigator.interfaces import InvalidBatchSizeError
 from lazr.restful.declarations import error_status
 import oops_amqp
 import pytz
+from six.moves import http_client
 import testtools
 from timeline.timeline import Timeline
 from zope.interface import directlyProvides
@@ -257,7 +257,7 @@ class TestErrorReportingUtility(TestCaseWithFactory):
 
         # Exceptions with a error_status in the 500 range result
         # in OOPSes.
-        @error_status(httplib.INTERNAL_SERVER_ERROR)
+        @error_status(http_client.INTERNAL_SERVER_ERROR)
         class InternalServerError(Exception):
             pass
         try:
@@ -268,7 +268,7 @@ class TestErrorReportingUtility(TestCaseWithFactory):
 
         # Exceptions with any other error_status do not result
         # in OOPSes.
-        @error_status(httplib.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 dd485b7..66b8b1d 100644
--- a/lib/lp/services/webapp/tests/test_login.py
+++ b/lib/lp/services/webapp/tests/test_login.py
@@ -17,7 +17,6 @@ from datetime import (
     datetime,
     timedelta,
     )
-import httplib
 import unittest
 import urllib
 import urlparse
@@ -31,6 +30,7 @@ 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 testtools.matchers import (
     Contains,
@@ -240,7 +240,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
                 person.account, email=test_email)
         self.assertTrue(view.login_called)
         response = view.request.response
-        self.assertEqual(httplib.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
@@ -409,7 +409,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
             view, html = self._createAndRenderView(openid_response)
         self.assertTrue(view.login_called)
         response = view.request.response
-        self.assertEqual(httplib.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)
@@ -577,7 +577,7 @@ class TestOpenIDCallbackView(TestCaseWithFactory):
             view_class=StubbedOpenIDCallbackViewLoggedIn)
         self.assertFalse(view.login_called)
         response = view.request.response
-        self.assertEqual(httplib.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
@@ -625,7 +625,7 @@ class TestOpenIDCallbackRedirects(TestCaseWithFactory):
         view.initialize()
         view._redirect()
         self.assertEqual(
-            httplib.TEMPORARY_REDIRECT, view.request.response.getStatus())
+            http_client.TEMPORARY_REDIRECT, view.request.response.getStatus())
         self.assertEqual(
             view.request.response.getHeader('Location'), self.STARTING_URL)
 
@@ -639,7 +639,7 @@ class TestOpenIDCallbackRedirects(TestCaseWithFactory):
         view.initialize()
         view._redirect()
         self.assertEqual(
-            httplib.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(
-            httplib.TEMPORARY_REDIRECT, view.request.response.getStatus())
+            http_client.TEMPORARY_REDIRECT, view.request.response.getStatus())
         self.assertEqual(
             view.request.response.getHeader('Location'), self.APPLICATION_URL)
 
@@ -678,12 +678,12 @@ class TestOpenIDReplayAttack(TestCaseWithFactory):
         self.assertEqual('Login', browser.title)
         fill_login_form_and_submit(browser, 'test@xxxxxxxxxxxxx')
         self.assertEqual(
-            httplib.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(
-            httplib.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 8fe724e..1a0250e 100644
--- a/lib/lp/services/webhooks/interfaces.py
+++ b/lib/lp/services/webhooks/interfaces.py
@@ -22,8 +22,6 @@ __all__ = [
     'ValidWebhookEventTypeVocabulary',
     ]
 
-import httplib
-
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -42,6 +40,7 @@ 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,
@@ -81,7 +80,7 @@ WEBHOOK_EVENT_TYPES = {
     }
 
 
-@error_status(httplib.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 b408462..1bad725 100644
--- a/lib/lp/snappy/interfaces/snap.py
+++ b/lib/lp/snappy/interfaces/snap.py
@@ -38,8 +38,6 @@ __all__ = [
     'SnapPrivateFeatureDisabled',
     ]
 
-import httplib
-
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -67,6 +65,7 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -125,7 +124,7 @@ SNAP_TESTING_FLAGS = {
     }
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class SnapBuildAlreadyPending(Exception):
     """A build was requested when an identical build was already pending."""
 
@@ -134,7 +133,7 @@ class SnapBuildAlreadyPending(Exception):
             "An identical build of this snap package is already pending.")
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class SnapBuildArchiveOwnerMismatch(Forbidden):
     """Builds against private archives require that owners match.
 
@@ -152,7 +151,7 @@ class SnapBuildArchiveOwnerMismatch(Forbidden):
             "if the snap package owner and the archive owner are equal.")
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class SnapBuildDisallowedArchitecture(Exception):
     """A build was requested for a disallowed architecture."""
 
@@ -162,7 +161,7 @@ class SnapBuildDisallowedArchitecture(Exception):
             (das.distroseries.getSuite(pocket), das.architecturetag))
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class SnapPrivateFeatureDisabled(Unauthorized):
     """Only certain users can create private snap objects."""
 
@@ -171,7 +170,7 @@ class SnapPrivateFeatureDisabled(Unauthorized):
             "You do not have permission to create private snaps")
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class DuplicateSnapName(Exception):
     """Raised for snap packages with duplicate name/owner."""
 
@@ -180,7 +179,7 @@ class DuplicateSnapName(Exception):
             "There is already a snap package with the same name and owner.")
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class SnapNotOwner(Unauthorized):
     """The registrant/requester is not the owner or a member of its team."""
 
@@ -190,7 +189,7 @@ class NoSuchSnap(NameLookupFailed):
     _message_prefix = "No such snap package with this owner"
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NoSourceForSnap(Exception):
     """Snap packages must have a source (Bazaar or Git branch)."""
 
@@ -200,12 +199,12 @@ class NoSourceForSnap(Exception):
             "branch.")
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class BadSnapSource(Exception):
     """The elements of the source for a snap package are inconsistent."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class SnapPrivacyMismatch(Exception):
     """Snap package privacy does not match its content."""
 
@@ -219,7 +218,7 @@ class BadSnapSearchContext(Exception):
     """The context is not valid for a snap package search."""
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class CannotModifySnapProcessor(Exception):
     """Tried to enable or disable a restricted processor on an snap package."""
 
@@ -232,17 +231,17 @@ class CannotModifySnapProcessor(Exception):
             self._fmt % {'processor': processor.name})
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotAuthorizeStoreUploads(Exception):
     """Cannot authorize uploads of a snap package to the store."""
 
 
-@error_status(httplib.INTERNAL_SERVER_ERROR)
+@error_status(http_client.INTERNAL_SERVER_ERROR)
 class SnapAuthorizationBadMacaroon(Exception):
     """The macaroon generated to authorize store uploads is unusable."""
 
 
-@error_status(httplib.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 da85ec7..9d3c586 100644
--- a/lib/lp/snappy/interfaces/snapbase.py
+++ b/lib/lp/snappy/interfaces/snapbase.py
@@ -13,8 +13,6 @@ __all__ = [
     "NoSuchSnapBase",
     ]
 
-import httplib
-
 from lazr.restful.declarations import (
     call_with,
     collection_default_content,
@@ -32,6 +30,7 @@ from lazr.restful.declarations import (
     REQUEST_USER,
     )
 from lazr.restful.fields import Reference
+from six.moves import http_client
 from zope.component import getUtility
 from zope.interface import Interface
 from zope.schema import (
@@ -58,7 +57,7 @@ class NoSuchSnapBase(NameLookupFailed):
     _message_prefix = "No such base"
 
 
-@error_status(httplib.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 f52e006..3531f2d 100644
--- a/lib/lp/snappy/interfaces/snapbuild.py
+++ b/lib/lp/snappy/interfaces/snapbuild.py
@@ -16,8 +16,6 @@ __all__ = [
     'SnapBuildStoreUploadStatus',
     ]
 
-import httplib
-
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -35,6 +33,7 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
+from six.moves import http_client
 from zope.component.interfaces import IObjectEvent
 from zope.interface import (
     Attribute,
@@ -65,7 +64,7 @@ from lp.soyuz.interfaces.archive import IArchive
 from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
 
 
-@error_status(httplib.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 efd5081..b35a38c 100644
--- a/lib/lp/snappy/interfaces/snapstoreclient.py
+++ b/lib/lp/snappy/interfaces/snapstoreclient.py
@@ -20,9 +20,8 @@ __all__ = [
     'UploadNotScannedYetResponse',
     ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from zope.interface import Interface
 
 
@@ -37,7 +36,7 @@ class SnapStoreError(Exception):
         self.can_retry = can_retry
 
 
-@error_status(httplib.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 aa8b8dd..aa82840 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]
 
-    >>> import httplib
-    >>> con = httplib.HTTPConnection(netloc)
+    >>> from six.moves import http_client
+    >>> con = http_client.HTTPConnection(netloc)
     >>> con.request("HEAD", path)
     >>> resp = con.getresponse()
     >>> headers = dict(resp.getheaders())
diff --git a/lib/lp/soyuz/interfaces/archive.py b/lib/lp/soyuz/interfaces/archive.py
index d24e502..d5e7e06 100644
--- a/lib/lp/soyuz/interfaces/archive.py
+++ b/lib/lp/soyuz/interfaces/archive.py
@@ -54,7 +54,6 @@ __all__ = [
     'validate_external_dependencies',
     ]
 
-import httplib
 import re
 from urlparse import urlparse
 
@@ -81,6 +80,7 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -123,7 +123,7 @@ from lp.soyuz.interfaces.component import IComponent
 NAMED_AUTH_TOKEN_FEATURE_FLAG = u"soyuz.named_auth_token.allow_new"
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class ArchiveDependencyError(Exception):
     """Raised when an `IArchiveDependency` does not fit the context archive.
 
@@ -137,12 +137,12 @@ class ArchiveDependencyError(Exception):
 
 # Exceptions used in the webservice that need to be in this file to get
 # picked up therein.
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotCopy(Exception):
     """Exception raised when a copy cannot be performed."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class CannotSwitchPrivacy(Exception):
     """Raised when switching the privacy of an archive that has
     publishing records."""
@@ -153,17 +153,17 @@ class PocketNotFound(NameLookupFailed):
     _message_prefix = "No such pocket"
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class AlreadySubscribed(Exception):
     """Raised when creating a subscription for a subscribed person."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class ArchiveNotPrivate(Exception):
     """Raised when creating an archive subscription for a public archive."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class NoTokensForTeams(Exception):
     """Raised when creating a token for a team, rather than a person."""
 
@@ -173,7 +173,7 @@ class ComponentNotFound(NameLookupFailed):
     _message_prefix = 'No such component'
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class InvalidComponent(Exception):
     """Invalid component name."""
 
@@ -193,17 +193,17 @@ class NoSuchPPA(NameLookupFailed):
     _message_prefix = "No such ppa"
 
 
-@error_status(httplib.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(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class ArchiveAlreadyDeleted(Exception):
     """Archive already deleted."""
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class CannotUploadToArchive(Exception):
     """A reason for not being able to upload to an archive."""
 
@@ -220,7 +220,7 @@ class InvalidPocketForPartnerArchive(CannotUploadToArchive):
     _fmt = "Partner uploads must be for the RELEASE or PROPOSED pocket."
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class CannotUploadToPocket(Exception):
     """Returned when a pocket is closed for uploads."""
 
@@ -230,7 +230,7 @@ class CannotUploadToPocket(Exception):
             "'%s' state." % (pocket.name, distroseries.status.name))
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class RedirectedPocket(Exception):
     """Returned for a pocket that would normally be redirected to another.
 
@@ -301,7 +301,7 @@ class CannotUploadToSeries(CannotUploadToArchive):
             distroseries=distroseries.name)
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class InvalidExternalDependencies(Exception):
     """Tried to set external dependencies to an invalid value."""
 
@@ -311,7 +311,7 @@ class InvalidExternalDependencies(Exception):
         self.errors = errors
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class CannotModifyArchiveProcessor(Exception):
     """Tried to enable or disable a restricted processor on an archive."""
 
@@ -324,13 +324,13 @@ class CannotModifyArchiveProcessor(Exception):
             self._fmt % {'processor': processor.name})
 
 
-@error_status(httplib.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(httplib.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 5284ff1..8546a85 100644
--- a/lib/lp/soyuz/interfaces/binarypackagebuild.py
+++ b/lib/lp/soyuz/interfaces/binarypackagebuild.py
@@ -14,8 +14,6 @@ __all__ = [
     'UnparsableDependencies',
     ]
 
-import httplib
-
 from lazr.enum import (
     EnumeratedType,
     Item,
@@ -31,6 +29,7 @@ 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,
@@ -51,7 +50,7 @@ from lp.soyuz.interfaces.publishing import ISourcePackagePublishingHistory
 from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease
 
 
-@error_status(httplib.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 8f5caa1..862c646 100644
--- a/lib/lp/soyuz/interfaces/distroarchseries.py
+++ b/lib/lp/soyuz/interfaces/distroarchseries.py
@@ -13,8 +13,6 @@ __all__ = [
     'IPocketChroot',
     ]
 
-import httplib
-
 from lazr.restful.declarations import (
     call_with,
     error_status,
@@ -31,6 +29,7 @@ from lazr.restful.fields import (
     Reference,
     ReferenceChoice,
     )
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -56,12 +55,12 @@ from lp.soyuz.enums import DistroArchSeriesFilterSense
 from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class InvalidChrootUploaded(Exception):
     """Raised when the sha1sum of an uploaded chroot does not match."""
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class ChrootNotPublic(Exception):
     """Raised when trying to set a chroot from a private livefs build."""
 
@@ -70,7 +69,7 @@ class ChrootNotPublic(Exception):
             "Cannot set chroot from a private build.")
 
 
-@error_status(httplib.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 c530dc8..11a7ead 100644
--- a/lib/lp/soyuz/interfaces/livefs.py
+++ b/lib/lp/soyuz/interfaces/livefs.py
@@ -22,8 +22,6 @@ __all__ = [
     'NoSuchLiveFS',
     ]
 
-import httplib
-
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -44,6 +42,7 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
+from six.moves import http_client
 from zope.interface import Interface
 from zope.schema import (
     Bool,
@@ -79,7 +78,7 @@ LIVEFS_FEATURE_FLAG = u"soyuz.livefs.allow_new"
 LIVEFS_WEBHOOKS_FEATURE_FLAG = u"soyuz.livefs.webhooks.enabled"
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class LiveFSBuildAlreadyPending(Exception):
     """A build was requested when an identical build was already pending."""
 
@@ -89,7 +88,7 @@ class LiveFSBuildAlreadyPending(Exception):
             "pending.")
 
 
-@error_status(httplib.FORBIDDEN)
+@error_status(http_client.FORBIDDEN)
 class LiveFSBuildArchiveOwnerMismatch(Forbidden):
     """Builds into private archives require that owners match.
 
@@ -108,7 +107,7 @@ class LiveFSBuildArchiveOwnerMismatch(Forbidden):
             "equal.")
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class LiveFSFeatureDisabled(Unauthorized):
     """Only certain users can create new LiveFS-related objects."""
 
@@ -118,7 +117,7 @@ class LiveFSFeatureDisabled(Unauthorized):
             "new live filesystem builds.")
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class DuplicateLiveFSName(Exception):
     """Raised for live filesystems with duplicate name/owner/distroseries."""
 
@@ -128,7 +127,7 @@ class DuplicateLiveFSName(Exception):
             "and distroseries.")
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class LiveFSNotOwner(Unauthorized):
     """The registrant/requester is not the owner or a member of its team."""
 
@@ -138,7 +137,7 @@ class NoSuchLiveFS(NameLookupFailed):
     _message_prefix = "No such live filesystem with this owner/distroseries"
 
 
-@error_status(httplib.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 13d1e87..77d0b85 100644
--- a/lib/lp/soyuz/interfaces/packagediff.py
+++ b/lib/lp/soyuz/interfaces/packagediff.py
@@ -11,9 +11,8 @@ __all__ = [
     'PackageDiffAlreadyRequested',
     ]
 
-import httplib
-
 from lazr.restful.declarations import error_status
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -29,7 +28,7 @@ from lp.services.librarian.interfaces import ILibraryFileAlias
 from lp.soyuz.enums import PackageDiffStatus
 
 
-@error_status(httplib.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 edb7f14..6660532 100644
--- a/lib/lp/soyuz/interfaces/packageset.py
+++ b/lib/lp/soyuz/interfaces/packageset.py
@@ -12,8 +12,6 @@ __all__ = [
     'NoSuchPackageSet',
     ]
 
-import httplib
-
 from lazr.restful.declarations import (
     collection_default_content,
     error_status,
@@ -31,6 +29,7 @@ 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,
@@ -54,7 +53,7 @@ class NoSuchPackageSet(NameLookupFailed):
     _message_prefix = "No such package set (in the specified distro series)"
 
 
-@error_status(httplib.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 06412ae..02c3615 100644
--- a/lib/lp/soyuz/interfaces/publishing.py
+++ b/lib/lp/soyuz/interfaces/publishing.py
@@ -25,8 +25,6 @@ __all__ = [
     'name_priority_map',
     ]
 
-import httplib
-
 from lazr.restful.declarations import (
     call_with,
     error_status,
@@ -42,6 +40,7 @@ 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,
@@ -98,12 +97,12 @@ class MissingSymlinkInPool(Exception):
     """
 
 
-@error_status(httplib.BAD_REQUEST)
+@error_status(http_client.BAD_REQUEST)
 class OverrideError(Exception):
     """Raised when an attempt to change an override fails."""
 
 
-@error_status(httplib.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 7bda98a..5a1679f 100644
--- a/lib/lp/soyuz/interfaces/queue.py
+++ b/lib/lp/soyuz/interfaces/queue.py
@@ -24,8 +24,6 @@ __all__ = [
     'QueueStateWriteProtectedError'
     ]
 
-import httplib
-
 from lazr.lifecycle.snapshot import doNotSnapshot
 from lazr.restful.declarations import (
     call_with,
@@ -42,6 +40,7 @@ from lazr.restful.fields import (
     CollectionField,
     Reference,
     )
+from six.moves import http_client
 from zope.interface import (
     Attribute,
     Interface,
@@ -73,7 +72,7 @@ class QueueStateWriteProtectedError(Exception):
     """
 
 
-@error_status(httplib.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 787e114..20b7b2f 100644
--- a/lib/lp/soyuz/tests/test_archive.py
+++ b/lib/lp/soyuz/tests/test_archive.py
@@ -11,12 +11,12 @@ from datetime import (
     timedelta,
     )
 import doctest
-import httplib
 import os.path
 
 from pytz import UTC
 import responses
 import six
+from six.moves import http_client
 from storm.store import Store
 from testtools.matchers import (
     AllMatch,
@@ -3896,7 +3896,7 @@ class TestGetSigningKeyData(TestCaseWithFactory):
             error = self.assertRaises(
                 GPGKeyDoesNotExistOnServer, ppa.getSigningKeyData)
         error_view = create_webservice_error_view(error)
-        self.assertEqual(httplib.NOT_FOUND, error_view.status)
+        self.assertEqual(http_client.NOT_FOUND, error_view.status)
 
     @responses.activate
     def test_getSigningKeyData_keyserver_failure(self):
@@ -3909,7 +3909,7 @@ class TestGetSigningKeyData(TestCaseWithFactory):
             error = self.assertRaises(
                 GPGKeyTemporarilyNotFoundError, ppa.getSigningKeyData)
         error_view = create_webservice_error_view(error)
-        self.assertEqual(httplib.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 04a161d..50a78c5 100644
--- a/lib/lp/testing/xmlrpc.py
+++ b/lib/lp/testing/xmlrpc.py
@@ -8,9 +8,9 @@ __all__ = [
     ]
 
 from cStringIO import StringIO
-import httplib
 import xmlrpclib
 
+from six.moves import http_client
 from zope.security.management import (
     endInteraction,
     queryInteraction,
@@ -26,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 httplib.HTTPResponse expects.
+    This is used because it is what http_client.HTTPResponse expects.
     """
     def __init__(self, output):
         self._output = output
@@ -35,7 +35,7 @@ class _FakeSocket(object):
         return StringIO(self._output)
 
 
-class TestHTTPConnection(httplib.HTTPConnection):
+class TestHTTPConnection(http_client.HTTPConnection):
     """A HTTPConnection which talks to http() instead of a real server.
 
     Only the methods called by xmlrpclib are overridden.
@@ -71,7 +71,7 @@ class TestHTTPConnection(httplib.HTTPConnection):
     def getresponse(self, buffering=False):
         content = self._zope_response().getOutput()
         sock = _FakeSocket(content)
-        response = httplib.HTTPResponse(sock)
+        response = http_client.HTTPResponse(sock)
         response.begin()
         return response
 
diff --git a/lib/lp/translations/interfaces/translationimportqueue.py b/lib/lp/translations/interfaces/translationimportqueue.py
index 1de94e0..bea463e 100644
--- a/lib/lp/translations/interfaces/translationimportqueue.py
+++ b/lib/lp/translations/interfaces/translationimportqueue.py
@@ -2,7 +2,6 @@
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 from datetime import timedelta
-import httplib
 
 from lazr.enum import (
     DBEnumeratedType,
@@ -26,6 +25,7 @@ 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,
@@ -78,7 +78,7 @@ class TranslationImportQueueConflictError(
     conflicts with existing entries."""
 
 
-@error_status(httplib.UNAUTHORIZED)
+@error_status(http_client.UNAUTHORIZED)
 class UserCannotSetTranslationImportStatus(Unauthorized):
     """User not permitted to change status.
 
diff --git a/utilities/paste b/utilities/paste
index b2df8e0..873807b 100755
--- a/utilities/paste
+++ b/utilities/paste
@@ -10,7 +10,6 @@ from cookielib import (
     Cookie,
     CookieJar,
     )
-import httplib
 from optparse import OptionParser
 import os
 import pwd