Skip to content

Commit 90c82ae

Browse files
jsiroischrismatix
andauthored
Root reqs that specify prereleases imply --pre. (#3004)
Fixes #3003 --------- Co-authored-by: Christoph Pröschel <[email protected]>
1 parent 49f86d2 commit 90c82ae

File tree

4 files changed

+172
-2
lines changed

4 files changed

+172
-2
lines changed

CHANGES.md

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

3+
## 2.69.1
4+
5+
This release fixes `--venv-repository` handling of top-level requirements that specify pre-releases.
6+
Such resolves now imply `--pre`.
7+
8+
* Root reqs that specify prereleases imply `--pre`. (#3004)
9+
310
## 2.69.0
411

512
This release adds a `pexec` console script as an alias for `pex3 run`.

pex/resolve/venv_resolver.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,15 @@ def _resolve_from_venv(
504504
)
505505
local_project_requirements = OrderedSet() # type: OrderedSet[LocalProjectRequirement]
506506
root_requirements = OrderedSet() # type: OrderedSet[Requirement]
507+
root_requirements_has_prereleases = False
507508
for parsed_requirement in parsed_requirements:
508509
if isinstance(parsed_requirement, LocalProjectRequirement):
509510
local_project_requirements.add(parsed_requirement)
510511
else:
512+
root_requirements_has_prereleases = (
513+
root_requirements_has_prereleases
514+
or parsed_requirement.requirement.specifier.prereleases
515+
)
511516
root_requirements.add(parsed_requirement.requirement)
512517
direct_requirements_by_project_name[
513518
parsed_requirement.requirement.project_name
@@ -537,7 +542,9 @@ def _resolve_from_venv(
537542
requirements=root_requirements,
538543
constraints_by_project_name=constraints_by_project_name,
539544
dependency_configuration=dependency_configuration,
540-
allow_prereleases=pip_configuration.allow_prereleases,
545+
allow_prereleases=(
546+
root_requirements_has_prereleases or pip_configuration.allow_prereleases
547+
),
541548
compile=compile,
542549
ignore_errors=ignore_errors,
543550
result_type=result_type,

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.69.0"
4+
__version__ = "2.69.1"
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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 os.path
7+
import re
8+
import subprocess
9+
from textwrap import dedent
10+
11+
import pytest
12+
13+
from pex.common import safe_open, touch
14+
from pex.compatibility import commonpath
15+
from pex.interpreter import PythonInterpreter
16+
from pex.venv.virtualenv import Virtualenv
17+
from testing import run_pex_command
18+
from testing.pytest_utils.tmp import Tempdir
19+
20+
21+
@pytest.fixture
22+
def project_dir(tmpdir):
23+
# type: (Tempdir) -> str
24+
25+
project_dir = tmpdir.join("project")
26+
with safe_open(os.path.join(project_dir, "pyproject.toml"), "w") as fp:
27+
fp.write(
28+
dedent(
29+
"""\
30+
[build-system]
31+
requires = ["uv_build>=0.9,<0.10.0"]
32+
build-backend = "uv_build"
33+
34+
[project]
35+
name = "project"
36+
version = "0.42.0"
37+
description = "Repro of issue 3003"
38+
requires-python = "==3.10.*"
39+
dependencies = [
40+
"opentelemetry-semantic-conventions==0.59b0",
41+
]
42+
"""
43+
)
44+
)
45+
touch(os.path.join(project_dir, "src", "project", "__init__.py"))
46+
return project_dir
47+
48+
49+
@pytest.fixture
50+
def project_venv(project_dir):
51+
# type: (str) -> Virtualenv
52+
53+
subprocess.check_call(args=["uv", "sync"], cwd=project_dir)
54+
return Virtualenv(os.path.join(project_dir, ".venv"))
55+
56+
57+
def assert_opentelemetry_semconv(
58+
python, # type: PythonInterpreter
59+
pex_root, # type: str
60+
pex, # type: str
61+
):
62+
# type: (...) -> None
63+
64+
output = (
65+
subprocess.check_output(
66+
args=[
67+
python.binary,
68+
pex,
69+
"-c",
70+
"from opentelemetry import semconv; print(semconv.__file__)",
71+
]
72+
)
73+
.decode("utf-8")
74+
.strip()
75+
)
76+
77+
assert pex_root == commonpath((pex_root, output))
78+
79+
80+
def test_edge_case_semver_version_satisfied(
81+
tmpdir, # type: Tempdir
82+
project_dir, # type: str
83+
project_venv, # type: Virtualenv
84+
py310, # type: PythonInterpreter
85+
):
86+
# type: (...) -> None
87+
88+
pex_root = tmpdir.join("pex-root")
89+
pex = tmpdir.join("project.pex")
90+
run_pex_command(
91+
args=[
92+
"--pex-root",
93+
pex_root,
94+
"--runtime-pex-root",
95+
pex_root,
96+
"--pip-version",
97+
"latest-compatible",
98+
"--venv-repository",
99+
project_venv.venv_dir,
100+
"project",
101+
"-o",
102+
pex,
103+
"--no-compress",
104+
],
105+
python=project_venv.interpreter.binary,
106+
).assert_failure(
107+
expected_error_re=r".*^{error_msg}$".format(
108+
error_msg=re.escape(
109+
"Resolve from venv at {venv_dir} failed: The virtual environment has "
110+
"opentelemetry-semantic-conventions 0.59b0 installed but it does not meet top "
111+
"level requirement project -> opentelemetry-semantic-conventions==0.59b0.".format(
112+
venv_dir=project_venv.venv_dir
113+
)
114+
),
115+
),
116+
re_flags=re.DOTALL | re.MULTILINE,
117+
)
118+
119+
run_pex_command(
120+
args=[
121+
"--pex-root",
122+
pex_root,
123+
"--runtime-pex-root",
124+
pex_root,
125+
"--pip-version",
126+
"latest-compatible",
127+
"--venv-repository",
128+
project_venv.venv_dir,
129+
"project",
130+
"-o",
131+
pex,
132+
"--no-compress",
133+
"--pre",
134+
],
135+
python=project_venv.interpreter.binary,
136+
).assert_success()
137+
assert_opentelemetry_semconv(python=py310, pex_root=pex_root, pex=pex)
138+
139+
run_pex_command(
140+
args=[
141+
"--pex-root",
142+
pex_root,
143+
"--runtime-pex-root",
144+
pex_root,
145+
"--pip-version",
146+
"latest-compatible",
147+
"--venv-repository",
148+
project_venv.venv_dir,
149+
"opentelemetry-semantic-conventions==0.59b0",
150+
"-o",
151+
pex,
152+
"--no-compress",
153+
],
154+
python=project_venv.interpreter.binary,
155+
).assert_success()
156+
assert_opentelemetry_semconv(python=py310, pex_root=pex_root, pex=pex)

0 commit comments

Comments
 (0)