Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions news/14187.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Support ``--no-binary`` with ``-r pylock.toml``. Before, pip would get the
sdist from the index instead of the locked URL, or fail if no wheel were
available available in the lock file.
2 changes: 1 addition & 1 deletion src/pip/_internal/cli/req_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ def get_requirements(
"without prior warning."
)
for package, package_dist in select_from_pylock_path_or_url(
filename, session=session
filename, session=session, format_control=options.format_control
):
req_to_add, locked_link = install_req_from_pylock_package(
package,
Expand Down
15 changes: 12 additions & 3 deletions src/pip/_internal/utils/pylock.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Pylock,
is_valid_pylock_path,
)
from pip._vendor.packaging.utils import NormalizedName
from pip._vendor.packaging.version import Version

from pip._internal.exceptions import DiagnosticPipError, InstallationError
Expand All @@ -25,6 +26,7 @@
from pip._internal.utils.urls import path_to_url, url_to_path

if TYPE_CHECKING:
from pip._internal.index.package_finder import FormatControl
from pip._internal.network.session import PipSession
from pip._internal.req.req_install import InstallRequirement

Expand Down Expand Up @@ -267,6 +269,7 @@ def _get_pylock_path_or_url_content(path_or_url: str, session: PipSession) -> st
def select_from_pylock_path_or_url(
pylock_path_or_url: str,
session: PipSession,
format_control: FormatControl | None,
) -> Iterator[
tuple[
Package,
Expand All @@ -289,10 +292,16 @@ def select_from_pylock_path_or_url(
f"Invalid pylock file {pylock_path_or_url!r}: {exc}"
) from exc

def prefer_sdist_predicate(name: NormalizedName) -> bool:
if format_control is None:
return False
allowed_formats = format_control.get_allowed_formats(name)
if "source" in allowed_formats and "binary" not in allowed_formats:
return True
return False

try:
# TODO: for completeness, pylock.select should support preferring sdist
# over wheels to support --no-binary
yield from lock.select()
yield from lock.select(prefer_sdist_predicate=prefer_sdist_predicate)
except Exception as exc:
raise InstallationError(
f"Cannot select requirements from pylock file {pylock_path_or_url!r}: {exc}"
Expand Down
19 changes: 19 additions & 0 deletions tests/data/lockfiles/pylock.onepackage.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
lock-version = "1.0"
created-by = "pip"

[[packages]]
name = "simplewheel"
version = "2.0"

[packages.sdist]
path = "../packages/simplewheel-2.0.tar.gz"

[packages.sdist.hashes]
sha256 = "d1e1fceaf0b5eac764843e4a16ba62394a4fd85896c87a4439aab0af087af1ed"

[[packages.wheels]]
name = "simplewheel-2.0-1-py2.py3-none-any.whl"
path = "../packages/simplewheel-2.0-1-py2.py3-none-any.whl"

[packages.wheels.hashes]
sha256 = "71e1ca6b16ae3382a698c284013f66504f2581099b2ce4801f60e9536236ceee"
Binary file added tests/data/packages/simplewheel-2.0.tar.gz
Binary file not shown.
29 changes: 29 additions & 0 deletions tests/functional/test_install_pylock_reqs.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,35 @@ def test_install_pylock_select_error(
assert "Cannot select requirements from pylock file" in result.stderr


def test_install_pylock_no_binary_selects_sdist(
script: PipTestEnvironment,
data: TestData,
tmp_path: Path,
) -> None:
pylock_path = data.lockfiles.joinpath("pylock.onepackage.toml")
report = tmp_path / "report.json"
result = script.pip(
"install",
"--no-index",
"--find-links",
data.common_wheels, # to obtain build backend to build sdist
"--dry-run",
"-r",
pylock_path,
"--no-binary=simplewheel",
"--report",
report,
allow_stderr_warning=True,
)
assert "experimental" in result.stderr
assert "Would install simplewheel-2.0" in result.stdout
# check that the sdist was selected
report_json = json.loads(report.read_text())
installed = report_json["install"]
assert installed[0]["metadata"]["name"] == "simplewheel"
assert installed[0]["download_info"]["url"].endswith(".tar.gz")


def test_install_pylock_no_binary(
script: PipTestEnvironment,
data: TestData,
Expand Down
Loading