diff --git a/news/5749.feature b/news/5749.feature new file mode 100644 index 00000000000..7a5995de681 --- /dev/null +++ b/news/5749.feature @@ -0,0 +1,2 @@ +For consistency, passing ``--no-cache-dir`` no longer affects whether wheels +will be built. In this case, a temporary directory is used. diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index 1c244d230b9..c13da44c6c3 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -33,6 +33,43 @@ logger = logging.getLogger(__name__) +def is_wheel_installed(): + """ + Return whether the wheel package is installed. + """ + try: + import wheel # noqa: F401 + except ImportError: + return False + + return True + + +def build_wheels(builder, pep517_requirements, legacy_requirements, session): + """ + Build wheels for requirements, depending on whether wheel is installed. + """ + # We don't build wheels for legacy requirements if wheel is not installed. + should_build_legacy = is_wheel_installed() + + # Always build PEP 517 requirements + build_failures = builder.build( + pep517_requirements, + session=session, autobuilding=True + ) + + if should_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 +364,18 @@ def run(self, options, args): 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, ) - 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 00000000000..c04a61118b1 --- /dev/null +++ b/tests/unit/test_command_install.py @@ -0,0 +1,68 @@ +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='', + ) + + return (builder.build.mock_calls, build_failures) + + @patch('pip._internal.commands.install.is_wheel_installed') + def test_build_wheels__wheel_installed(self, is_wheel_installed): + is_wheel_installed.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.is_wheel_installed') + def test_build_wheels__wheel_not_installed(self, is_wheel_installed): + is_wheel_installed.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']