Skip to content

Commit ddf932e

Browse files
committed
Handle --only-final with -r pylock.toml
Release control behaves identically for requirements coming from lock files and other requirements.
1 parent f7bfe28 commit ddf932e

7 files changed

Lines changed: 97 additions & 0 deletions

File tree

news/13950.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Honor ``--only-final`` when sourcing requirements with ``-r pylock.toml``.

src/pip/_internal/cli/req_command.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ def get_requirements(
353353
package_dist,
354354
filename,
355355
options.format_control,
356+
options.release_control,
356357
user_supplied=True,
357358
)
358359
)

src/pip/_internal/req/constructors.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from pip._internal.models.format_control import FormatControl
2727
from pip._internal.models.index import PyPI, TestPyPI
2828
from pip._internal.models.link import Link
29+
from pip._internal.models.release_control import ReleaseControl
2930
from pip._internal.models.wheel import Wheel
3031
from pip._internal.req.req_file import ParsedRequirement
3132
from pip._internal.req.req_install import InstallRequirement
@@ -595,6 +596,7 @@ def install_req_from_pylock_package(
595596
),
596597
pylock_path_or_url: str,
597598
format_control: FormatControl,
599+
release_control: ReleaseControl | None,
598600
user_supplied: bool,
599601
) -> InstallRequirement:
600602
pass
@@ -666,6 +668,17 @@ def install_req_from_pylock_package(
666668
requirement_url = package_sdist_requirement_url(
667669
pylock_path_or_url, package_dist
668670
)
671+
if (
672+
release_control is not None
673+
and version.is_prerelease
674+
# is False is intentional as allows_prereleases is tri-valued
675+
and release_control.allows_prereleases(package.name) is False
676+
):
677+
raise InstallationError(
678+
f"Only final releases are allowed for package {package.name!r} "
679+
f"but it is pinned to a prerelease version {version!s} "
680+
f"in {pylock_path_or_url!r}."
681+
)
669682
ireq = InstallRequirement(
670683
req=Requirement(f"{package.name}=={version}"),
671684
comes_from=pylock_path_or_url,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
lock-version = "1.0"
2+
created-by = "pip"
3+
4+
[[packages]]
5+
name = "pkg-prerelease"
6+
7+
[packages.archive]
8+
path = "../packages/pkg_prerelease-1.0a1-py3-none-any.whl"
9+
10+
[packages.archive.hashes]
11+
sha256 = "5b170526e52d17d1b2e0162c006142e792293a7975a1f51df39035f1b14768d5"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
lock-version = "1.0"
2+
created-by = "pip"
3+
4+
[[packages]]
5+
name = "pkg-prerelease"
6+
version = "1.0a1"
7+
8+
[[packages.wheels]]
9+
name = "pkg_prerelease-1.0a1-py3-none-any.whl"
10+
path = "../packages/pkg_prerelease-1.0a1-py3-none-any.whl"
11+
12+
[packages.wheels.hashes]
13+
sha256 = "5b170526e52d17d1b2e0162c006142e792293a7975a1f51df39035f1b14768d5"
993 Bytes
Binary file not shown.

tests/functional/test_install_pylock_reqs.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,61 @@ def test_install_pylock_only_binary_ignored_for_archives(
197197
)
198198
assert "experimental" in result.stderr
199199
assert "Would install simple2-3.0" in result.stdout
200+
201+
202+
def test_install_pylock_default_prerelease(
203+
script: PipTestEnvironment,
204+
shared_data: TestData,
205+
) -> None:
206+
"""Prereleases are allowed by default."""
207+
pylock_path = shared_data.lockfiles.joinpath("pylock.prerelease-wheel.toml")
208+
result = script.pip(
209+
"install",
210+
"--no-index",
211+
"--dry-run",
212+
"-r",
213+
pylock_path,
214+
allow_stderr_warning=True,
215+
)
216+
assert "experimental" in result.stderr
217+
assert "Would install pkg-prerelease-1.0a1" in result.stdout
218+
219+
220+
def test_install_pylock_reject_prerelease(
221+
script: PipTestEnvironment,
222+
shared_data: TestData,
223+
) -> None:
224+
"""Prereleases are rejected when --only-final is set."""
225+
pylock_path = shared_data.lockfiles.joinpath("pylock.prerelease-wheel.toml")
226+
result = script.pip(
227+
"install",
228+
"--no-index",
229+
"--dry-run",
230+
"-r",
231+
pylock_path,
232+
"--only-final=pkg-prerelease",
233+
expect_error=True,
234+
)
235+
assert (
236+
"Only final releases are allowed for package 'pkg-prerelease' "
237+
"but it is pinned to a prerelease version 1.0a1" in result.stderr
238+
)
239+
240+
241+
def test_install_pylock_allow_archive_prerelease(
242+
script: PipTestEnvironment,
243+
shared_data: TestData,
244+
) -> None:
245+
"""--only-final does not influence direct URL requirements."""
246+
pylock_path = shared_data.lockfiles.joinpath("pylock.prerelease-archive.toml")
247+
result = script.pip(
248+
"install",
249+
"--no-index",
250+
"--dry-run",
251+
"-r",
252+
pylock_path,
253+
"--only-final=pkg-prerelease",
254+
allow_stderr_warning=True,
255+
)
256+
assert "experimental" in result.stderr
257+
assert "Would install pkg-prerelease-1.0a1" in result.stdout

0 commit comments

Comments
 (0)