Skip to content

Commit e858eab

Browse files
authored
Allow exceptions for --no-wheel & --no-build. (#3023)
Fixes #3022
1 parent 0ce118e commit e858eab

File tree

6 files changed

+108
-53
lines changed

6 files changed

+108
-53
lines changed

CHANGES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Release Notes
22

3+
## 2.71.1
4+
5+
This release fixes Pex to allow blanket disallowing builds but making targeted exceptions and
6+
vice-versa. The underlying Pip machinery has always supported this, but Pex just got in the way for
7+
no reason.
8+
9+
* Allow exceptions for `--no-wheel` & `--no-build`. (#3023)
10+
311
## 2.71.0
412

513
This release upgrades the floor of `science` to 0.16.0 to pick up support for generating PEX scies

pex/pip/tool.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -561,16 +561,15 @@ def _iter_build_configuration_options(self, build_configuration):
561561
if not build_configuration.allow_builds:
562562
yield "--only-binary"
563563
yield ":all:"
564-
elif not build_configuration.allow_wheels:
564+
if not build_configuration.allow_wheels:
565565
yield "--no-binary"
566566
yield ":all:"
567-
else:
568-
for project in build_configuration.only_wheels:
569-
yield "--only-binary"
570-
yield str(project)
571-
for project in build_configuration.only_builds:
572-
yield "--no-binary"
573-
yield str(project)
567+
for project in build_configuration.only_wheels:
568+
yield "--only-binary"
569+
yield str(project)
570+
for project in build_configuration.only_builds:
571+
yield "--no-binary"
572+
yield str(project)
574573

575574
if build_configuration.prefer_older_binary:
576575
yield "--prefer-binary"

pex/resolve/resolver_configuration.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,6 @@ def __attrs_post_init__(self):
101101
"Cannot both disallow builds and disallow wheels. Please allow one of these or "
102102
"both so that some distributions can be resolved."
103103
)
104-
if not self.allow_builds and self.only_builds:
105-
raise self.Error(
106-
"Builds were disallowed, but the following project names are configured to only "
107-
"allow building: {only_builds}".format(
108-
only_builds=", ".join(sorted(map(str, self.only_builds)))
109-
)
110-
)
111-
if not self.allow_wheels and self.only_wheels:
112-
raise self.Error(
113-
"Resolving wheels was disallowed, but the following project names are configured "
114-
"to only allow resolving pre-built wheels: {only_wheels}".format(
115-
only_wheels=", ".join(sorted(map(str, self.only_wheels)))
116-
)
117-
)
118104

119105
contradictory_only = self.only_builds.intersection(self.only_wheels)
120106
if contradictory_only:

pex/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Copyright 2015 Pex project contributors.
22
# Licensed under the Apache License, Version 2.0 (see LICENSE).
33

4-
__version__ = "2.71.0"
4+
__version__ = "2.71.1"
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Copyright 2025 Pex project contributors.
2+
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3+
4+
from __future__ import absolute_import
5+
6+
import subprocess
7+
from textwrap import dedent
8+
9+
from pex.typing import TYPE_CHECKING
10+
from testing import run_pex_command
11+
from testing.pytest_utils.tmp import Tempdir
12+
13+
if TYPE_CHECKING:
14+
import colors # vendor:skip
15+
else:
16+
from pex.third_party import colors
17+
18+
19+
def build_cyan_penguin_pex_assert_only_cowsay_built(
20+
tmpdir, # type: Tempdir
21+
*extra_args # type: str
22+
):
23+
# type: (...) -> None
24+
25+
with open(tmpdir.join("exe.py"), "w") as exe_fp:
26+
exe_fp.write(
27+
dedent(
28+
"""\
29+
# /// script
30+
# dependencies = [
31+
# "ansicolors",
32+
# "cowsay<6",
33+
# ]
34+
# ///
35+
36+
import sys
37+
38+
import colors
39+
import cowsay
40+
41+
42+
cowsay.tux(colors.cyan(" ".join(sys.argv[1:])))
43+
"""
44+
)
45+
)
46+
47+
pex_root = tmpdir.join("pex-root")
48+
pex = tmpdir.join("pex")
49+
pip_log = tmpdir.join("pip.log")
50+
run_pex_command(
51+
args=[
52+
"--pex-root",
53+
pex_root,
54+
"--runtime-pex-root",
55+
pex_root,
56+
"--pip-log",
57+
pip_log,
58+
"--exe",
59+
exe_fp.name,
60+
"-o",
61+
pex,
62+
]
63+
+ list(extra_args)
64+
).assert_success()
65+
66+
assert "| {message} |".format(message=colors.cyan("Moo?")) in subprocess.check_output(
67+
args=[pex, "Moo?"]
68+
).decode("utf-8")
69+
70+
with open(pip_log) as fp:
71+
pip_source_log_lines = [line for line in fp if "Source in " in line]
72+
assert 1 == len(pip_source_log_lines), "Should have built 1 distribution."
73+
assert "which satisfies requirement cowsay<6" in pip_source_log_lines[0], pip_source_log_lines[
74+
0
75+
]
76+
77+
78+
def test_no_build_exception_allowed(tmpdir):
79+
# type: (Tempdir) -> None
80+
81+
build_cyan_penguin_pex_assert_only_cowsay_built(tmpdir, "--no-build", "--only-build", "cowsay")
82+
83+
84+
def test_no_wheel_exception_allowed(tmpdir):
85+
# type: (Tempdir) -> None
86+
87+
# Under modern versions of Pip, setuptools may also be built from source as part of setting up
88+
# the PEP-517 build environment for cowsay; so we prevent this to avoid complications in the
89+
# assertion.
90+
build_cyan_penguin_pex_assert_only_cowsay_built(
91+
tmpdir, "--no-wheel", "--only-wheel", "ansicolors", "--only-wheel", "setuptools"
92+
)

tests/resolve/test_resolver_options.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -265,36 +265,6 @@ def test_build_configuration_invalid_no_builds_no_wheels(parser):
265265
compute_build_configuration(parser, args=["--no-build", "--no-wheel"])
266266

267267

268-
def test_build_configuration_invalid_no_builds_only_build(parser):
269-
# type: (ArgumentParser) -> None
270-
resolver_options.register(parser)
271-
272-
with pytest.raises(
273-
BuildConfiguration.Error,
274-
match=re.escape(
275-
"Builds were disallowed, but the following project names are configured to only allow "
276-
"building: ansicolors"
277-
),
278-
):
279-
compute_build_configuration(parser, args=["--no-build", "--only-build", "ansicolors"])
280-
281-
282-
def test_build_configuration_invalid_no_wheels_only_wheel(parser):
283-
# type: (ArgumentParser) -> None
284-
resolver_options.register(parser)
285-
286-
with pytest.raises(
287-
BuildConfiguration.Error,
288-
match=re.escape(
289-
"Resolving wheels was disallowed, but the following project names are configured to "
290-
"only allow resolving pre-built wheels: ansicolors, cowsay"
291-
),
292-
):
293-
compute_build_configuration(
294-
parser, args=["--no-wheel", "--only-wheel", "cowsay", "--only-wheel", "ansicolors"]
295-
)
296-
297-
298268
def test_build_configuration_invalid_only_build_only_wheel(parser):
299269
# type: (ArgumentParser) -> None
300270
resolver_options.register(parser)

0 commit comments

Comments
 (0)