Skip to content

Commit

Permalink
Merge pull request #2082 from sethmlarson/format-control-ordering
Browse files Browse the repository at this point in the history
Fix ordering of format controls to preserve behavior of pip
  • Loading branch information
webknjaz authored May 2, 2024
2 parents 1feadbc + d4d5fd4 commit ad79078
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
22 changes: 20 additions & 2 deletions piptools/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,27 @@ def write_trusted_hosts(self) -> Iterator[str]:
yield f"--trusted-host {trusted_host}"

def write_format_controls(self) -> Iterator[str]:
for nb in dedup(sorted(self.format_control.no_binary)):
# The ordering of output needs to preserve the behavior of pip's
# FormatControl.get_allowed_formats(). The behavior is the following:
#
# * Parsing of CLI options happens first to last.
# * --only-binary takes precedence over --no-binary
# * Package names take precedence over :all:
# * We'll never see :all: in both due to mutual exclusion.
#
# So in summary, we want to emit :all: first and then package names later.
no_binary = self.format_control.no_binary.copy()
only_binary = self.format_control.only_binary.copy()

if ":all:" in no_binary:
yield "--no-binary :all:"
no_binary.remove(":all:")
if ":all:" in only_binary:
yield "--only-binary :all:"
only_binary.remove(":all:")
for nb in dedup(sorted(no_binary)):
yield f"--no-binary {nb}"
for ob in dedup(sorted(self.format_control.only_binary)):
for ob in dedup(sorted(only_binary)):
yield f"--only-binary {ob}"

def write_find_links(self) -> Iterator[str]:
Expand Down
35 changes: 35 additions & 0 deletions tests/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,41 @@ def test_write_format_controls(writer):
assert lines == expected_lines


@pytest.mark.parametrize(
("no_binary", "only_binary", "expected_lines"),
(
(
[":all:"],
["django"],
[
"--no-binary :all:",
"--only-binary django",
],
),
(
["django"],
[":all:"],
[
"--only-binary :all:",
"--no-binary django",
],
),
),
)
def test_write_format_controls_all(writer, no_binary, only_binary, expected_lines):
"""
Tests --no-binary/--only-binary options
with the value of :all:. We want to preserve
the FormatControl behavior so we emit :all:
first before packages.
"""

writer.format_control = FormatControl(no_binary=no_binary, only_binary=only_binary)
lines = list(writer.write_format_controls())

assert lines == expected_lines


@pytest.mark.parametrize(
("index_urls", "expected_lines"),
(
Expand Down

0 comments on commit ad79078

Please sign in to comment.