Repository: pypa/pip

Issue:
Move PipXmlrpcTransport from pip._internal.download to pip._internal.network.xmlrpc
**What's the problem this feature will solve?**

`pip._internal.download` contains `PipXmlrpcTransport`, but that would make more sense in its own module (reducing mental overhead of working in `pip._internal.download`).

**Describe the solution you'd like**

We should move it to `pip._internal.network.xmlrpc` (and move any associated tests to `tests.unit.test_network_xmlrpc`).

**Additional context**

PRs that can be referenced for the kinds of changes required:

* #7045
* #7062
* #7089

----

This issue is a good starting point for anyone who wants to help out with pip's development -- it's simple and the process of fixing this should be a good introduction to pip's development workflow.


Discussion:

Resolving patch:
diff --git a/src/pip/_internal/commands/search.py b/src/pip/_internal/commands/search.py
--- a/src/pip/_internal/commands/search.py
+++ b/src/pip/_internal/commands/search.py
@@ -14,9 +14,9 @@
 from pip._internal.cli.base_command import Command
 from pip._internal.cli.req_command import SessionCommandMixin
 from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
-from pip._internal.download import PipXmlrpcTransport
 from pip._internal.exceptions import CommandError
 from pip._internal.models.index import PyPI
+from pip._internal.network.xmlrpc import PipXmlrpcTransport
 from pip._internal.utils.compat import get_terminal_size
 from pip._internal.utils.logging import indent_log
 from pip._internal.utils.misc import write_output
diff --git a/src/pip/_internal/download.py b/src/pip/_internal/download.py
--- a/src/pip/_internal/download.py
+++ b/src/pip/_internal/download.py
@@ -17,9 +17,6 @@
 from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response
 from pip._vendor.requests.structures import CaseInsensitiveDict
 from pip._vendor.six import PY2
-# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is
-#       why we ignore the type on this import
-from pip._vendor.six.moves import xmlrpc_client  # type: ignore
 from pip._vendor.six.moves.urllib import parse as urllib_parse
 
 import pip
@@ -804,35 +801,6 @@ def unpack_file_url(
         _copy_file(from_path, download_dir, link)
 
 
-class PipXmlrpcTransport(xmlrpc_client.Transport):
-    """Provide a `xmlrpclib.Transport` implementation via a `PipSession`
-    object.
-    """
-
-    def __init__(self, index_url, session, use_datetime=False):
-        xmlrpc_client.Transport.__init__(self, use_datetime)
-        index_parts = urllib_parse.urlparse(index_url)
-        self._scheme = index_parts.scheme
-        self._session = session
-
-    def request(self, host, handler, request_body, verbose=False):
-        parts = (self._scheme, host, handler, None, None, None)
-        url = urllib_parse.urlunparse(parts)
-        try:
-            headers = {'Content-Type': 'text/xml'}
-            response = self._session.post(url, data=request_body,
-                                          headers=headers, stream=True)
-            response.raise_for_status()
-            self.verbose = verbose
-            return self.parse_response(response.raw)
-        except requests.HTTPError as exc:
-            logger.critical(
-                "HTTP error %s while getting %s",
-                exc.response.status_code, url,
-            )
-            raise
-
-
 def unpack_url(
     link,  # type: Link
     location,  # type: str
diff --git a/src/pip/_internal/network/xmlrpc.py b/src/pip/_internal/network/xmlrpc.py
new file mode 100644
--- /dev/null
+++ b/src/pip/_internal/network/xmlrpc.py
@@ -0,0 +1,40 @@
+"""xmlrpclib.Transport implementation
+"""
+import logging
+
+from pip._vendor import requests
+# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is
+#       why we ignore the type on this import
+from pip._vendor.six.moves import xmlrpc_client  # type: ignore
+from pip._vendor.six.moves.urllib import parse as urllib_parse
+
+logger = logging.getLogger(__name__)
+
+
+class PipXmlrpcTransport(xmlrpc_client.Transport):
+    """Provide a `xmlrpclib.Transport` implementation via a `PipSession`
+    object.
+    """
+
+    def __init__(self, index_url, session, use_datetime=False):
+        xmlrpc_client.Transport.__init__(self, use_datetime)
+        index_parts = urllib_parse.urlparse(index_url)
+        self._scheme = index_parts.scheme
+        self._session = session
+
+    def request(self, host, handler, request_body, verbose=False):
+        parts = (self._scheme, host, handler, None, None, None)
+        url = urllib_parse.urlunparse(parts)
+        try:
+            headers = {'Content-Type': 'text/xml'}
+            response = self._session.post(url, data=request_body,
+                                          headers=headers, stream=True)
+            response.raise_for_status()
+            self.verbose = verbose
+            return self.parse_response(response.raw)
+        except requests.HTTPError as exc:
+            logger.critical(
+                "HTTP error %s while getting %s",
+                exc.response.status_code, url,
+            )
+            raise


Test patch: