From cf5ce5f16fd6bbd5c8be54e2c53df8ea5ca70c9b Mon Sep 17 00:00:00 2001 From: NtaleGrey Date: Fri, 27 Sep 2019 17:54:11 +0300 Subject: [PATCH 1/2] Move PipXmlrpcTransport from pip._internal.download to pip._internal.network.xmlrpc --- news/7090.removal | 2 ++ src/pip/_internal/commands/search.py | 2 +- src/pip/_internal/download.py | 30 ----------------------- src/pip/_internal/network/xmlrpc.py | 36 ++++++++++++++++++++++++++++ tests/functional/test_search.py | 27 --------------------- tests/unit/test_network_xmlrpc.py | 30 +++++++++++++++++++++++ 6 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 news/7090.removal create mode 100644 src/pip/_internal/network/xmlrpc.py create mode 100644 tests/unit/test_network_xmlrpc.py diff --git a/news/7090.removal b/news/7090.removal new file mode 100644 index 000000000..01bdcf654 --- /dev/null +++ b/news/7090.removal @@ -0,0 +1,2 @@ +Move PipXmlrpcTransport from pip._internal.download to pip._internal.network.xmlrpc +and move associated tests to tests.unit.test_network_xmlrpc diff --git a/src/pip/_internal/commands/search.py b/src/pip/_internal/commands/search.py index ef698d0b7..23e9ca8fe 100644 --- a/src/pip/_internal/commands/search.py +++ b/src/pip/_internal/commands/search.py @@ -14,7 +14,7 @@ from pip._vendor.six.moves import xmlrpc_client # type: ignore 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.network.xmlrpc import PipXmlrpcTransport from pip._internal.exceptions import CommandError from pip._internal.models.index import PyPI from pip._internal.utils.compat import get_terminal_size diff --git a/src/pip/_internal/download.py b/src/pip/_internal/download.py index 92d5ab501..9b813d3de 100644 --- a/src/pip/_internal/download.py +++ b/src/pip/_internal/download.py @@ -19,7 +19,6 @@ 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 +803,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 index 000000000..042f3ff75 --- /dev/null +++ b/src/pip/_internal/network/xmlrpc.py @@ -0,0 +1,36 @@ +import logging + +from pip._vendor import requests +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 diff --git a/tests/functional/test_search.py b/tests/functional/test_search.py index fce6c5f81..86c19b37c 100644 --- a/tests/functional/test_search.py +++ b/tests/functional/test_search.py @@ -4,7 +4,6 @@ import pretend import pytest from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS -from pip._internal.commands import create_command from pip._internal.commands.search import ( highest_version, print_results, @@ -106,32 +105,6 @@ def test_search_missing_argument(script): assert 'ERROR: Missing required argument (search query).' in result.stderr -@pytest.mark.network -def test_run_method_should_return_success_when_find_packages(): - """ - Test SearchCommand.run for found package - """ - command = create_command('search') - cmdline = "--index=https://pypi.org/pypi pip" - with command.main_context(): - options, args = command.parse_args(cmdline.split()) - status = command.run(options, args) - assert status == SUCCESS - - -@pytest.mark.network -def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs(): - """ - Test SearchCommand.run for no matches - """ - command = create_command('search') - cmdline = "--index=https://pypi.org/pypi nonexistentpackage" - with command.main_context(): - options, args = command.parse_args(cmdline.split()) - status = command.run(options, args) - assert status == NO_MATCHES_FOUND - - @pytest.mark.network def test_search_should_exit_status_code_zero_when_find_packages(script): """ diff --git a/tests/unit/test_network_xmlrpc.py b/tests/unit/test_network_xmlrpc.py new file mode 100644 index 000000000..58abb4f21 --- /dev/null +++ b/tests/unit/test_network_xmlrpc.py @@ -0,0 +1,30 @@ +import pytest + +from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.commands import create_command + + +@pytest.mark.network +def test_run_method_should_return_success_when_find_packages(): + """ + Test SearchCommand.run for found package + """ + command = create_command('search') + cmdline = "--index=https://pypi.org/pypi pip" + with command.main_context(): + options, args = command.parse_args(cmdline.split()) + status = command.run(options, args) + assert status == SUCCESS + + +@pytest.mark.network +def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs(): + """ + Test SearchCommand.run for no matches + """ + command = create_command('search') + cmdline = "--index=https://pypi.org/pypi nonexistentpackage" + with command.main_context(): + options, args = command.parse_args(cmdline.split()) + status = command.run(options, args) + assert status == NO_MATCHES_FOUND From 88e9ce6e27a97c8d742f245762f576568125b86c Mon Sep 17 00:00:00 2001 From: NtaleGrey Date: Fri, 27 Sep 2019 20:11:19 +0300 Subject: [PATCH 2/2] implement feedback --- news/{7090.removal => 7090.trivial} | 0 src/pip/_internal/commands/search.py | 2 +- src/pip/_internal/download.py | 2 -- src/pip/_internal/network/xmlrpc.py | 4 ++++ tests/functional/test_search.py | 27 +++++++++++++++++++++++++ tests/unit/test_network_xmlrpc.py | 30 ---------------------------- 6 files changed, 32 insertions(+), 33 deletions(-) rename news/{7090.removal => 7090.trivial} (100%) delete mode 100644 tests/unit/test_network_xmlrpc.py diff --git a/news/7090.removal b/news/7090.trivial similarity index 100% rename from news/7090.removal rename to news/7090.trivial diff --git a/src/pip/_internal/commands/search.py b/src/pip/_internal/commands/search.py index 23e9ca8fe..9ae1fb533 100644 --- a/src/pip/_internal/commands/search.py +++ b/src/pip/_internal/commands/search.py @@ -14,9 +14,9 @@ from pip._vendor.six.moves import xmlrpc_client # type: ignore 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.network.xmlrpc 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 index 9b813d3de..6cf3e5e64 100644 --- a/src/pip/_internal/download.py +++ b/src/pip/_internal/download.py @@ -17,8 +17,6 @@ from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter 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.urllib import parse as urllib_parse import pip diff --git a/src/pip/_internal/network/xmlrpc.py b/src/pip/_internal/network/xmlrpc.py index 042f3ff75..40d20595a 100644 --- a/src/pip/_internal/network/xmlrpc.py +++ b/src/pip/_internal/network/xmlrpc.py @@ -1,6 +1,10 @@ +"""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 diff --git a/tests/functional/test_search.py b/tests/functional/test_search.py index 86c19b37c..fce6c5f81 100644 --- a/tests/functional/test_search.py +++ b/tests/functional/test_search.py @@ -4,6 +4,7 @@ import pretend import pytest from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.commands import create_command from pip._internal.commands.search import ( highest_version, print_results, @@ -105,6 +106,32 @@ def test_search_missing_argument(script): assert 'ERROR: Missing required argument (search query).' in result.stderr +@pytest.mark.network +def test_run_method_should_return_success_when_find_packages(): + """ + Test SearchCommand.run for found package + """ + command = create_command('search') + cmdline = "--index=https://pypi.org/pypi pip" + with command.main_context(): + options, args = command.parse_args(cmdline.split()) + status = command.run(options, args) + assert status == SUCCESS + + +@pytest.mark.network +def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs(): + """ + Test SearchCommand.run for no matches + """ + command = create_command('search') + cmdline = "--index=https://pypi.org/pypi nonexistentpackage" + with command.main_context(): + options, args = command.parse_args(cmdline.split()) + status = command.run(options, args) + assert status == NO_MATCHES_FOUND + + @pytest.mark.network def test_search_should_exit_status_code_zero_when_find_packages(script): """ diff --git a/tests/unit/test_network_xmlrpc.py b/tests/unit/test_network_xmlrpc.py deleted file mode 100644 index 58abb4f21..000000000 --- a/tests/unit/test_network_xmlrpc.py +++ /dev/null @@ -1,30 +0,0 @@ -import pytest - -from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS -from pip._internal.commands import create_command - - -@pytest.mark.network -def test_run_method_should_return_success_when_find_packages(): - """ - Test SearchCommand.run for found package - """ - command = create_command('search') - cmdline = "--index=https://pypi.org/pypi pip" - with command.main_context(): - options, args = command.parse_args(cmdline.split()) - status = command.run(options, args) - assert status == SUCCESS - - -@pytest.mark.network -def test_run_method_should_return_no_matches_found_when_does_not_find_pkgs(): - """ - Test SearchCommand.run for no matches - """ - command = create_command('search') - cmdline = "--index=https://pypi.org/pypi nonexistentpackage" - with command.main_context(): - options, args = command.parse_args(cmdline.split()) - status = command.run(options, args) - assert status == NO_MATCHES_FOUND