From 8e531be25516a7b37c171557fa9747ba0fc30619 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Wed, 27 Feb 2019 20:30:03 -0800 Subject: [PATCH] Refactor out build_wheels(), and test. --- src/pip/_internal/commands/install.py | 68 ++++++++++++++++--------- tests/unit/test_command_install.py | 71 +++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 tests/unit/test_command_install.py diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index 1c244d230..5ff4707ad 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -33,6 +33,45 @@ from pip._internal.wheel import WheelBuilder logger = logging.getLogger(__name__) +def should_build_legacy(options): + # We don't build wheels for legacy requirements if we + # don't have wheel installed or we don't have a cache dir + try: + import wheel # noqa: F401 + build_legacy = bool(options.cache_dir) + except ImportError: + build_legacy = False + + return build_legacy + + +def build_wheels( + builder, pep517_requirements, legacy_requirements, session, options, +): + """ + Build wheels for requirements, depending on whether wheel is installed. + """ + # We don't build wheels for legacy requirements if wheel is not installed. + build_legacy = should_build_legacy(options) + + # Always build PEP 517 requirements + build_failures = builder.build( + pep517_requirements, + session=session, autobuilding=True + ) + + if build_legacy: + # We don't care about failures building legacy + # requirements, as we'll fall through to a direct + # install for those. + builder.build( + legacy_requirements, + session=session, autobuilding=True + ) + + return build_failures + + class InstallCommand(RequirementCommand): """ Install packages from: @@ -327,34 +366,19 @@ class InstallCommand(RequirementCommand): else: legacy_requirements.append(req) - # We don't build wheels for legacy requirements if we - # don't have wheel installed or we don't have a cache dir - try: - import wheel # noqa: F401 - build_legacy = bool(options.cache_dir) - except ImportError: - build_legacy = False - - wb = WheelBuilder( + wheel_builder = WheelBuilder( finder, preparer, wheel_cache, build_options=[], global_options=[], ) - # Always build PEP 517 requirements - build_failures = wb.build( - pep517_requirements, - session=session, autobuilding=True + build_failures = build_wheels( + builder=wheel_builder, + pep517_requirements=pep517_requirements, + legacy_requirements=legacy_requirements, + session=session, + options=options, ) - if build_legacy: - # We don't care about failures building legacy - # requirements, as we'll fall through to a direct - # install for those. - wb.build( - legacy_requirements, - session=session, autobuilding=True - ) - # If we're using PEP 517, we cannot do a direct install # so we fail here. if build_failures: diff --git a/tests/unit/test_command_install.py b/tests/unit/test_command_install.py new file mode 100644 index 000000000..f718b8a2b --- /dev/null +++ b/tests/unit/test_command_install.py @@ -0,0 +1,71 @@ +from mock import Mock, call, patch + +from pip._internal.commands.install import build_wheels + + +class TestWheelCache: + + def check_build_wheels( + self, + pep517_requirements, + legacy_requirements, + session, + ): + """ + Return: (mock_calls, return_value). + """ + def build(reqs, **kwargs): + # Fail the first requirement. + return [reqs[0]] + + builder = Mock() + builder.build.side_effect = build + + build_failures = build_wheels( + builder=builder, + pep517_requirements=pep517_requirements, + legacy_requirements=legacy_requirements, + # A session value isn't needed. + session='', + options='' + ) + + return (builder.build.mock_calls, build_failures) + + @patch('pip._internal.commands.install.should_build_legacy') + def test_build_wheels__should_build_legacy_true(self, should_build_legacy): + should_build_legacy.return_value = True + + mock_calls, build_failures = self.check_build_wheels( + pep517_requirements=['a', 'b'], + legacy_requirements=['c', 'd'], + session='', + ) + + # Legacy requirements were built. + assert mock_calls == [ + call(['a', 'b'], autobuilding=True, session=''), + call(['c', 'd'], autobuilding=True, session=''), + ] + + # Legacy build failures are not included in the return value. + assert build_failures == ['a'] + + @patch('pip._internal.commands.install.should_build_legacy') + def test_build_wheels__should_build_legacy_false( + self, should_build_legacy, + ): + should_build_legacy.return_value = False + + mock_calls, build_failures = self.check_build_wheels( + pep517_requirements=['a', 'b'], + legacy_requirements=['c', 'd'], + session='', + ) + + # Legacy requirements were not built. + assert mock_calls == [ + call(['a', 'b'], autobuilding=True, session=''), + ] + + assert build_failures == ['a']