diff --git a/CHANGES.md b/CHANGES.md index 42f7444ca..448997e36 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,14 @@ # Release Notes +## 2.4.1 + +This release fixes `pex --only-binary X --lock ...` to work with lock +files also created with `--only-binary X`. The known case here is a +`--style universal` lock created with `--only-binary X` to achieve a +partially wheel-only universal lock. + +* Fix `pex --only-binary X --lock ...`. (#2433) + ## 2.4.0 This release brings new support for preserving arguments passed to the diff --git a/pex/resolve/lock_resolver.py b/pex/resolve/lock_resolver.py index 6dbba8291..983722427 100644 --- a/pex/resolve/lock_resolver.py +++ b/pex/resolve/lock_resolver.py @@ -103,9 +103,13 @@ def __init__( self._network_configuration = network_configuration self._password_entries = password_entries self._cache = cache + + # Since a VCSArtifactDownloadManager is only used for VCS requirements, a build is both + # required and preferred by the user. self._build_configuration = attr.evolve( - build_configuration, allow_wheels=False, allow_builds=True, prefer_older_binary=False + build_configuration, allow_builds=True, prefer_older_binary=False ) + self._pip_version = pip_version self._resolver = resolver self._use_pip_config = use_pip_config diff --git a/pex/version.py b/pex/version.py index e129d8425..7738a09ca 100644 --- a/pex/version.py +++ b/pex/version.py @@ -1,4 +1,4 @@ # Copyright 2015 Pex project contributors. # Licensed under the Apache License, Version 2.0 (see LICENSE). -__version__ = "2.4.0" +__version__ = "2.4.1" diff --git a/tests/integration/test_issue_2432.py b/tests/integration/test_issue_2432.py new file mode 100644 index 000000000..e76c704cb --- /dev/null +++ b/tests/integration/test_issue_2432.py @@ -0,0 +1,85 @@ +# Copyright 2024 Pex project contributors. +# Licensed under the Apache License, Version 2.0 (see LICENSE). + +import os.path +from textwrap import dedent + +from pex.compatibility import commonpath +from pex.targets import LocalInterpreter +from pex.typing import TYPE_CHECKING +from testing import run_pex_command +from testing.cli import run_pex3 + +if TYPE_CHECKING: + from typing import Any, Iterable, Optional + + +def test_lock_use_no_build_wheel(tmpdir): + # type: (Any)-> None + + lock = os.path.join(str(tmpdir), "lock") + run_pex3( + "lock", + "create", + "ansicolors==1.1.8", + "--only-binary", + "ansicolors", + "-o", + lock, + "--style", + "universal", + "--indent", + "2", + ).assert_success() + + def assert_pex_from_lock( + extra_args=(), # type: Iterable[str] + expected_error=None, # type: Optional[str] + ): + # type: (...) -> None + + pex_root = os.path.realpath(os.path.join(str(tmpdir), "pex_root")) + args = [ + "--pex-root", + pex_root, + "--runtime-pex-root", + pex_root, + "--lock", + lock, + "--", + "-c", + "import colors, os; print(os.path.realpath(colors.__file__))", + ] + result = run_pex_command(args=list(extra_args) + args) + if expected_error: + result.assert_failure() + assert expected_error in result.error + else: + result.assert_success() + assert pex_root == commonpath((pex_root, result.output.strip())) + + assert_pex_from_lock() + + # A redundant --only-binary should not matter. + assert_pex_from_lock(extra_args=["--only-binary", "ansicolors"]) + + # An extraneous --only-build should not matter. + assert_pex_from_lock(extra_args=["--only-build", "cowsay"]) + + # However; a conflicting --only-build should matter. + assert_pex_from_lock( + extra_args=["--only-build", "ansicolors"], + expected_error=dedent( + """\ + Failed to resolve all requirements for {target_description} from {lock}: + + Configured with: + build: True + only_build: ansicolors + use_wheel: True + + Dependency on ansicolors not satisfied, 1 incompatible candidate found: + 1.) ansicolors 1.1.8 (via: ansicolors==1.1.8) does not have any compatible artifacts: + """ + ).format(lock=lock, target_description=LocalInterpreter.create().render_description()), + )