Skip to content

Commit

Permalink
Order format controls to preserve behavior in pip
Browse files Browse the repository at this point in the history
  • Loading branch information
sethmlarson authored and webknjaz committed May 1, 2024
1 parent f83aed3 commit a105469
Show file tree
Hide file tree
Showing 2 changed files with 51 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
31 changes: 31 additions & 0 deletions tests/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,37 @@ def test_write_format_controls(writer):
assert lines == expected_lines


def test_write_format_controls_all(writer):
"""
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=[":all:"], only_binary=["django"]
)
lines = list(writer.write_format_controls())

expected_lines = [
"--no-binary :all:",
"--only-binary django",
]
assert lines == expected_lines

writer.format_control = FormatControl(
no_binary=["django"], only_binary=[":all:"]
)
lines = list(writer.write_format_controls())

expected_lines = [
"--only-binary :all:",
"--no-binary django",
]
assert lines == expected_lines


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

0 comments on commit a105469

Please sign in to comment.