Skip to content

Commit 6c44d43

Browse files
committed
Imply using new behavior when build constraints are provided without needing to use the build-constraint feature
1 parent d9d5f5d commit 6c44d43

File tree

6 files changed

+42
-48
lines changed

6 files changed

+42
-48
lines changed

docs/html/user_guide.rst

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -262,20 +262,16 @@ serve them in a centralized place.
262262
Build Constraints
263263
-----------------
264264

265-
.. versionadded:: 25.2
266-
.. note::
267-
268-
Build constraints are currently an **experimental feature** and must be
269-
enabled using ``--use-feature=build-constraint``.
265+
.. versionadded:: 25.3
270266

271-
Build constraints are a specialized type of constraints file that apply only
272-
to the build environment when building packages from source. Unlike regular
273-
constraints which affect the installed packages in your environment, build
267+
Build constraints are a type of constraints file that applies only to isolated
268+
build environments used for building packages from source. Unlike regular
269+
constraints, which affect the packages installed in your environment, build
274270
constraints only influence the versions of packages available during the
275271
build process.
276272

277-
This is particularly useful when you need to constrain build dependencies
278-
(like ``setuptools``, ``cython``, etc.) without affecting the
273+
This is useful when you need to constrain build dependencies
274+
(such as ``setuptools``, ``cython``, etc.) without affecting the
279275
final installed environment.
280276

281277
Use build constraints like so:
@@ -284,21 +280,21 @@ Use build constraints like so:
284280

285281
.. code-block:: shell
286282
287-
python -m pip install --build-constraint build-constraints.txt --use-feature=build-constraint SomePackage
283+
python -m pip install --build-constraint build-constraints.txt SomePackage
288284
289285
.. tab:: Windows
290286

291287
.. code-block:: shell
292288
293-
py -m pip install --build-constraint build-constraints.txt --use-feature=build-constraint SomePackage
289+
py -m pip install --build-constraint build-constraints.txt SomePackage
294290
295291
Example build constraints file (``build-constraints.txt``):
296292

297293
.. code-block:: text
298294
299295
# Constrain setuptools version during build
300-
setuptools>=45.0.0,<60.0.0
301-
# Pin Cython for packages that use it
296+
setuptools>=45,<80
297+
# Pin Cython for packages that use it to build
302298
cython==0.29.24
303299
304300

news/13534.feature.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
Add experimental build constraints support via ``--use-feature=build-constraint``.
2-
This allows constraining the versions of packages used during the build process
3-
(e.g., setuptools). Build constraints can be specified via ``PIP_BUILD_CONSTRAINT``
4-
environment variable or ``--build-constraint`` flag.
1+
Add support for build constraints via the ``--build-constraint`` option. This
2+
allows constraining the versions of packages used during the build process
3+
(e.g., setuptools).
4+
5+
When using ``--build-constraint``, you can no longer pass constraints to
6+
isolated build environments via the ``PIP_CONSTRAINT`` environment variable.
7+
To opt in to this behavior without specifying any build constraints, use
8+
``--use-feature=build-constraint``.

src/pip/_internal/build_env.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,23 +128,29 @@ def _deprecation_constraint_check(self) -> None:
128128
if self._build_constraint_feature_enabled:
129129
return
130130

131+
if self._build_constraints:
132+
return
133+
131134
if not self._constraints:
132135
return
133136

134137
if not os.environ.get("PIP_CONSTRAINT"):
135138
return
136139

137140
pip_constraint_files = [
138-
f.strip() for f in os.environ["PIP_CONSTRAINT"].split() if f.strip()
141+
f for f in os.environ["PIP_CONSTRAINT"].split() if f.strip()
139142
]
140-
if pip_constraint_files and set(pip_constraint_files) == set(self._constraints):
143+
if pip_constraint_files and pip_constraint_files == self._constraints:
141144
deprecated(
142145
reason=(
143146
"Setting PIP_CONSTRAINT will not affect "
144147
"build constraints in the future,"
145148
),
146149
replacement=(
147-
'PIP_BUILD_CONSTRAINT with PIP_USE_FEATURE="build-constraint"'
150+
"to specify build constraints use --build-constraint or "
151+
"PIP_BUILD_CONSTRAINT, to disable this warning without "
152+
"any build constraints set --use-feature=build-constraint or "
153+
'PIP_USE_FEATURE="build-constraint"'
148154
),
149155
gone_in="26.2",
150156
issue=None,
@@ -219,13 +225,17 @@ def install(
219225
# Handle build constraints
220226
extra_environ: ExtraEnviron = {}
221227
if self._build_constraint_feature_enabled:
228+
args.extend(["--use-feature", "build-constraint"])
229+
230+
if self._build_constraints:
222231
# Build constraints must be passed as both constraints
223-
# and build constraints to the subprocess
232+
# and build constraints, so that nested builds receive
233+
# build constraints
224234
for constraint_file in self._build_constraints:
225235
args.extend(["--constraint", constraint_file])
226236
args.extend(["--build-constraint", constraint_file])
227-
args.extend(["--use-feature", "build-constraint"])
228237

238+
if self._build_constraint_feature_enabled and not self._build_constraints:
229239
# If there are no build constraints but the build constraint
230240
# process is enabled then we must ignore regular constraints
231241
if not self._build_constraints:

src/pip/_internal/cli/cmdoptions.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,6 @@ def check_build_constraints(options: Values) -> None:
107107
:param options: The OptionParser options.
108108
"""
109109
if hasattr(options, "build_constraints") and options.build_constraints:
110-
if "build-constraint" not in options.features_enabled:
111-
raise CommandError(
112-
"To use --build-constraint, you must enable this feature with "
113-
"--use-feature=build-constraint."
114-
)
115110
if not options.build_isolation:
116111
raise CommandError(
117112
"--build-constraint cannot be used with --no-build-isolation."
@@ -457,8 +452,7 @@ def build_constraint() -> Option:
457452
metavar="file",
458453
help=(
459454
"Constrain build dependencies using the given constraints file. "
460-
"This option can be used multiple times. "
461-
"Requires --use-feature=build-constraint."
455+
"This option can be used multiple times."
462456
),
463457
)
464458

tests/functional/test_build_constraints.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ def _run_pip_install_with_build_constraints_no_feature_flag(
6969
"--build-constraint",
7070
str(constraints_file),
7171
str(project_dir),
72-
expect_error=True,
7372
)
7473

7574

@@ -164,13 +163,14 @@ def test_build_constraints_file_not_found(
164163
def test_build_constraints_without_feature_flag(
165164
script: PipTestEnvironment, tmpdir: Path
166165
) -> None:
167-
"""Test that --build-constraint requires the feature flag."""
166+
"""Test that --build-constraint automatically enables the feature."""
168167
project_dir = _create_simple_test_package(script=script, name="test_no_feature")
169168
constraints_file = _create_constraints_file(
170169
script=script, filename="constraints.txt", content="setuptools==45.0.0\n"
171170
)
172171
result = _run_pip_install_with_build_constraints_no_feature_flag(
173172
script=script, project_dir=project_dir, constraints_file=constraints_file
174173
)
175-
assert result.returncode != 0
176-
assert "build-constraint" in result.stderr.lower()
174+
# Should succeed now that --build-constraint auto-enables the feature
175+
assert result.returncode == 0
176+
_assert_successful_installation(result=result, package_name="test_no_feature")

tests/unit/test_build_constraints.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ def test_deprecation_check_warning_shown(self) -> None:
8181
"Setting PIP_CONSTRAINT will not affect build constraints in the future"
8282
in message
8383
)
84-
assert 'PIP_BUILD_CONSTRAINT with PIP_USE_FEATURE="build-constraint"' in message
84+
assert (
85+
"to specify build constraints use "
86+
"--build-constraint or PIP_BUILD_CONSTRAINT" in message
87+
)
8588

8689
@mock.patch.dict(os.environ, {"PIP_CONSTRAINT": "constraint1.txt constraint2.txt"})
8790
def test_deprecation_check_multiple_constraints(self) -> None:
@@ -96,19 +99,6 @@ def test_deprecation_check_multiple_constraints(self) -> None:
9699
with pytest.warns(PipDeprecationWarning):
97100
installer._deprecation_constraint_check()
98101

99-
@mock.patch.dict(os.environ, {"PIP_CONSTRAINT": "constraint1.txt constraint2.txt"})
100-
def test_deprecation_check_multiple_constraints_different_order(self) -> None:
101-
"""Test deprecation warning works when constraints are in different order."""
102-
finder = make_test_finder()
103-
installer = SubprocessBuildEnvironmentInstaller(
104-
finder,
105-
constraints=["constraint2.txt", "constraint1.txt"],
106-
build_constraint_feature_enabled=False,
107-
)
108-
109-
with pytest.warns(PipDeprecationWarning):
110-
installer._deprecation_constraint_check()
111-
112102
@mock.patch.dict(
113103
os.environ, {"PIP_CONSTRAINT": "constraint1.txt constraint2.txt extra.txt"}
114104
)

0 commit comments

Comments
 (0)