pip 25.2__py3-none-any.whl → 25.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. pip/__init__.py +1 -1
  2. pip/_internal/__init__.py +0 -0
  3. pip/_internal/build_env.py +71 -3
  4. pip/_internal/cache.py +1 -1
  5. pip/_internal/cli/cmdoptions.py +43 -71
  6. pip/_internal/cli/parser.py +3 -3
  7. pip/_internal/cli/req_command.py +46 -26
  8. pip/_internal/commands/download.py +4 -7
  9. pip/_internal/commands/install.py +19 -14
  10. pip/_internal/commands/lock.py +3 -6
  11. pip/_internal/commands/wheel.py +5 -10
  12. pip/_internal/configuration.py +1 -2
  13. pip/_internal/distributions/sdist.py +13 -14
  14. pip/_internal/exceptions.py +20 -3
  15. pip/_internal/index/package_finder.py +3 -3
  16. pip/_internal/metadata/__init__.py +7 -2
  17. pip/_internal/metadata/importlib/_dists.py +8 -2
  18. pip/_internal/models/link.py +1 -1
  19. pip/_internal/models/wheel.py +5 -66
  20. pip/_internal/network/cache.py +6 -11
  21. pip/_internal/network/lazy_wheel.py +5 -3
  22. pip/_internal/operations/build/wheel.py +4 -4
  23. pip/_internal/operations/build/wheel_editable.py +4 -4
  24. pip/_internal/operations/prepare.py +7 -1
  25. pip/_internal/pyproject.py +2 -61
  26. pip/_internal/req/__init__.py +1 -3
  27. pip/_internal/req/constructors.py +42 -38
  28. pip/_internal/req/req_file.py +0 -1
  29. pip/_internal/req/req_install.py +32 -141
  30. pip/_internal/resolution/resolvelib/candidates.py +20 -11
  31. pip/_internal/resolution/resolvelib/factory.py +31 -0
  32. pip/_internal/resolution/resolvelib/provider.py +9 -0
  33. pip/_internal/resolution/resolvelib/reporter.py +21 -8
  34. pip/_internal/resolution/resolvelib/resolver.py +2 -6
  35. pip/_internal/self_outdated_check.py +11 -3
  36. pip/_internal/utils/filesystem.py +12 -0
  37. pip/_internal/utils/unpacking.py +25 -0
  38. pip/_internal/wheel_builder.py +23 -96
  39. pip/_vendor/README.rst +180 -0
  40. pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  41. pip/_vendor/certifi/LICENSE +20 -0
  42. pip/_vendor/certifi/__init__.py +1 -1
  43. pip/_vendor/certifi/cacert.pem +62 -40
  44. pip/_vendor/dependency_groups/LICENSE.txt +9 -0
  45. pip/_vendor/distlib/LICENSE.txt +284 -0
  46. pip/_vendor/distro/LICENSE +202 -0
  47. pip/_vendor/idna/LICENSE.md +31 -0
  48. pip/_vendor/msgpack/COPYING +14 -0
  49. pip/_vendor/msgpack/__init__.py +2 -2
  50. pip/_vendor/packaging/LICENSE +3 -0
  51. pip/_vendor/packaging/LICENSE.APACHE +177 -0
  52. pip/_vendor/packaging/LICENSE.BSD +23 -0
  53. pip/_vendor/pkg_resources/LICENSE +17 -0
  54. pip/_vendor/platformdirs/LICENSE +21 -0
  55. pip/_vendor/platformdirs/api.py +1 -1
  56. pip/_vendor/platformdirs/macos.py +10 -8
  57. pip/_vendor/platformdirs/version.py +16 -3
  58. pip/_vendor/pygments/LICENSE +25 -0
  59. pip/_vendor/pyproject_hooks/LICENSE +21 -0
  60. pip/_vendor/requests/LICENSE +175 -0
  61. pip/_vendor/requests/__version__.py +2 -2
  62. pip/_vendor/requests/adapters.py +17 -40
  63. pip/_vendor/requests/sessions.py +1 -1
  64. pip/_vendor/resolvelib/LICENSE +13 -0
  65. pip/_vendor/resolvelib/__init__.py +1 -1
  66. pip/_vendor/resolvelib/resolvers/abstract.py +3 -3
  67. pip/_vendor/resolvelib/resolvers/resolution.py +5 -0
  68. pip/_vendor/rich/LICENSE +19 -0
  69. pip/_vendor/rich/style.py +7 -11
  70. pip/_vendor/tomli/LICENSE +21 -0
  71. pip/_vendor/tomli/__init__.py +1 -1
  72. pip/_vendor/tomli/_parser.py +28 -21
  73. pip/_vendor/tomli/_re.py +8 -5
  74. pip/_vendor/tomli_w/LICENSE +21 -0
  75. pip/_vendor/truststore/LICENSE +21 -0
  76. pip/_vendor/truststore/__init__.py +1 -1
  77. pip/_vendor/truststore/_api.py +14 -6
  78. pip/_vendor/truststore/_openssl.py +3 -1
  79. pip/_vendor/urllib3/LICENSE.txt +21 -0
  80. pip/_vendor/vendor.txt +8 -8
  81. {pip-25.2.dist-info → pip-25.3.dist-info}/METADATA +9 -10
  82. {pip-25.2.dist-info → pip-25.3.dist-info}/RECORD +106 -90
  83. {pip-25.2.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
  84. pip-25.3.dist-info/entry_points.txt +4 -0
  85. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +9 -0
  86. pip/_internal/operations/build/metadata_legacy.py +0 -73
  87. pip/_internal/operations/build/wheel_legacy.py +0 -119
  88. pip/_internal/operations/install/editable_legacy.py +0 -48
  89. pip/_internal/utils/setuptools_build.py +0 -149
  90. pip-25.2.dist-info/entry_points.txt +0 -3
  91. pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +0 -3
  92. pip-25.2.dist-info/top_level.txt +0 -1
  93. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/LICENSE.txt +0 -0
  94. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
  95. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
  96. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +0 -0
  97. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
  98. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
  99. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +0 -0
  100. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
  101. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
  102. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
  103. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
  104. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
  105. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
  106. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
  107. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
  108. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
  109. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
  110. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
  111. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
  112. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
  113. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
  114. {pip-25.2.dist-info → pip-25.3.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
pip/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "25.2"
3
+ __version__ = "25.3"
4
4
 
5
5
 
6
6
  def main(args: list[str] | None = None) -> int:
pip/_internal/__init__.py CHANGED
File without changes
@@ -11,7 +11,7 @@ import textwrap
11
11
  from collections import OrderedDict
12
12
  from collections.abc import Iterable
13
13
  from types import TracebackType
14
- from typing import TYPE_CHECKING, Protocol
14
+ from typing import TYPE_CHECKING, Protocol, TypedDict
15
15
 
16
16
  from pip._vendor.packaging.version import Version
17
17
 
@@ -19,6 +19,7 @@ from pip import __file__ as pip_location
19
19
  from pip._internal.cli.spinners import open_spinner
20
20
  from pip._internal.locations import get_platlib, get_purelib, get_scheme
21
21
  from pip._internal.metadata import get_default_environment, get_environment
22
+ from pip._internal.utils.deprecation import deprecated
22
23
  from pip._internal.utils.logging import VERBOSE
23
24
  from pip._internal.utils.packaging import get_requirement
24
25
  from pip._internal.utils.subprocess import call_subprocess
@@ -28,6 +29,10 @@ if TYPE_CHECKING:
28
29
  from pip._internal.index.package_finder import PackageFinder
29
30
  from pip._internal.req.req_install import InstallRequirement
30
31
 
32
+ class ExtraEnviron(TypedDict, total=False):
33
+ extra_environ: dict[str, str]
34
+
35
+
31
36
  logger = logging.getLogger(__name__)
32
37
 
33
38
 
@@ -101,8 +106,44 @@ class SubprocessBuildEnvironmentInstaller:
101
106
  Install build dependencies by calling pip in a subprocess.
102
107
  """
103
108
 
104
- def __init__(self, finder: PackageFinder) -> None:
109
+ def __init__(
110
+ self,
111
+ finder: PackageFinder,
112
+ build_constraints: list[str] | None = None,
113
+ build_constraint_feature_enabled: bool = False,
114
+ ) -> None:
105
115
  self.finder = finder
116
+ self._build_constraints = build_constraints or []
117
+ self._build_constraint_feature_enabled = build_constraint_feature_enabled
118
+
119
+ def _deprecation_constraint_check(self) -> None:
120
+ """
121
+ Check for deprecation warning: PIP_CONSTRAINT affecting build environments.
122
+
123
+ This warns when build-constraint feature is NOT enabled and PIP_CONSTRAINT
124
+ is not empty.
125
+ """
126
+ if self._build_constraint_feature_enabled or self._build_constraints:
127
+ return
128
+
129
+ pip_constraint = os.environ.get("PIP_CONSTRAINT")
130
+ if not pip_constraint or not pip_constraint.strip():
131
+ return
132
+
133
+ deprecated(
134
+ reason=(
135
+ "Setting PIP_CONSTRAINT will not affect "
136
+ "build constraints in the future,"
137
+ ),
138
+ replacement=(
139
+ "to specify build constraints using --build-constraint or "
140
+ "PIP_BUILD_CONSTRAINT. To disable this warning without "
141
+ "any build constraints set --use-feature=build-constraint or "
142
+ 'PIP_USE_FEATURE="build-constraint"'
143
+ ),
144
+ gone_in="26.2",
145
+ issue=None,
146
+ )
106
147
 
107
148
  def install(
108
149
  self,
@@ -112,6 +153,8 @@ class SubprocessBuildEnvironmentInstaller:
112
153
  kind: str,
113
154
  for_req: InstallRequirement | None,
114
155
  ) -> None:
156
+ self._deprecation_constraint_check()
157
+
115
158
  finder = self.finder
116
159
  args: list[str] = [
117
160
  sys.executable,
@@ -167,13 +210,38 @@ class SubprocessBuildEnvironmentInstaller:
167
210
  args.append("--pre")
168
211
  if finder.prefer_binary:
169
212
  args.append("--prefer-binary")
213
+
214
+ # Handle build constraints
215
+ if self._build_constraint_feature_enabled:
216
+ args.extend(["--use-feature", "build-constraint"])
217
+
218
+ if self._build_constraints:
219
+ # Build constraints must be passed as both constraints
220
+ # and build constraints, so that nested builds receive
221
+ # build constraints
222
+ for constraint_file in self._build_constraints:
223
+ args.extend(["--constraint", constraint_file])
224
+ args.extend(["--build-constraint", constraint_file])
225
+
226
+ extra_environ: ExtraEnviron = {}
227
+ if self._build_constraint_feature_enabled and not self._build_constraints:
228
+ # If there are no build constraints but the build constraints
229
+ # feature is enabled then we must ignore regular constraints
230
+ # in the isolated build environment
231
+ extra_environ = {"extra_environ": {"_PIP_IN_BUILD_IGNORE_CONSTRAINTS": "1"}}
232
+
170
233
  args.append("--")
171
234
  args.extend(requirements)
235
+
236
+ identify_requirement = (
237
+ f" for {for_req.name}" if for_req and for_req.name else ""
238
+ )
172
239
  with open_spinner(f"Installing {kind}") as spinner:
173
240
  call_subprocess(
174
241
  args,
175
- command_desc=f"pip subprocess to install {kind}",
242
+ command_desc=f"installing {kind}{identify_requirement}",
176
243
  spinner=spinner,
244
+ **extra_environ,
177
245
  )
178
246
 
179
247
 
pip/_internal/cache.py CHANGED
@@ -143,7 +143,7 @@ class SimpleWheelCache(Cache):
143
143
  wheel = Wheel(wheel_name)
144
144
  except InvalidWheelFilename:
145
145
  continue
146
- if canonicalize_name(wheel.name) != canonical_package_name:
146
+ if wheel.name != canonical_package_name:
147
147
  logger.debug(
148
148
  "Ignoring cached wheel %s for %s as it "
149
149
  "does not match the expected distribution name %s.",
@@ -11,7 +11,6 @@ pass on state. To be consistent, all options will follow this design.
11
11
  # mypy: strict-optional=False
12
12
  from __future__ import annotations
13
13
 
14
- import importlib.util
15
14
  import logging
16
15
  import os
17
16
  import pathlib
@@ -101,6 +100,29 @@ def check_dist_restriction(options: Values, check_target: bool = False) -> None:
101
100
  )
102
101
 
103
102
 
103
+ def check_build_constraints(options: Values) -> None:
104
+ """Function for validating build constraints options.
105
+
106
+ :param options: The OptionParser options.
107
+ """
108
+ if hasattr(options, "build_constraints") and options.build_constraints:
109
+ if not options.build_isolation:
110
+ raise CommandError(
111
+ "--build-constraint cannot be used with --no-build-isolation."
112
+ )
113
+
114
+ # Import here to avoid circular imports
115
+ from pip._internal.network.session import PipSession
116
+ from pip._internal.req.req_file import get_file_content
117
+
118
+ # Eagerly check build constraints file contents
119
+ # is valid so that we don't fail in when trying
120
+ # to check constraints in isolated build process
121
+ with PipSession() as session:
122
+ for constraint_file in options.build_constraints:
123
+ get_file_content(constraint_file, session)
124
+
125
+
104
126
  def _path_option_check(option: Option, opt: str, value: str) -> str:
105
127
  return os.path.expanduser(value)
106
128
 
@@ -161,8 +183,7 @@ require_virtualenv: Callable[..., Option] = partial(
161
183
  action="store_true",
162
184
  default=False,
163
185
  help=(
164
- "Allow pip to only run in a virtual environment; "
165
- "exit with an error otherwise."
186
+ "Allow pip to only run in a virtual environment; exit with an error otherwise."
166
187
  ),
167
188
  )
168
189
 
@@ -430,6 +451,21 @@ def constraints() -> Option:
430
451
  )
431
452
 
432
453
 
454
+ def build_constraints() -> Option:
455
+ return Option(
456
+ "--build-constraint",
457
+ dest="build_constraints",
458
+ action="append",
459
+ type="str",
460
+ default=[],
461
+ metavar="file",
462
+ help=(
463
+ "Constrain build dependencies using the given constraints file. "
464
+ "This option can be used multiple times."
465
+ ),
466
+ )
467
+
468
+
433
469
  def requirements() -> Option:
434
470
  return Option(
435
471
  "-r",
@@ -813,62 +849,16 @@ check_build_deps: Callable[..., Option] = partial(
813
849
  dest="check_build_deps",
814
850
  action="store_true",
815
851
  default=False,
816
- help="Check the build dependencies when PEP517 is used.",
852
+ help="Check the build dependencies.",
817
853
  )
818
854
 
819
855
 
820
- def _handle_no_use_pep517(
821
- option: Option, opt: str, value: str, parser: OptionParser
822
- ) -> None:
823
- """
824
- Process a value provided for the --no-use-pep517 option.
825
-
826
- This is an optparse.Option callback for the no_use_pep517 option.
827
- """
828
- # Since --no-use-pep517 doesn't accept arguments, the value argument
829
- # will be None if --no-use-pep517 is passed via the command-line.
830
- # However, the value can be non-None if the option is triggered e.g.
831
- # by an environment variable, for example "PIP_NO_USE_PEP517=true".
832
- if value is not None:
833
- msg = """A value was passed for --no-use-pep517,
834
- probably using either the PIP_NO_USE_PEP517 environment variable
835
- or the "no-use-pep517" config file option. Use an appropriate value
836
- of the PIP_USE_PEP517 environment variable or the "use-pep517"
837
- config file option instead.
838
- """
839
- raise_option_error(parser, option=option, msg=msg)
840
-
841
- # If user doesn't wish to use pep517, we check if setuptools is installed
842
- # and raise error if it is not.
843
- packages = ("setuptools",)
844
- if not all(importlib.util.find_spec(package) for package in packages):
845
- msg = (
846
- f"It is not possible to use --no-use-pep517 "
847
- f"without {' and '.join(packages)} installed."
848
- )
849
- raise_option_error(parser, option=option, msg=msg)
850
-
851
- # Otherwise, --no-use-pep517 was passed via the command-line.
852
- parser.values.use_pep517 = False
853
-
854
-
855
856
  use_pep517: Any = partial(
856
857
  Option,
857
858
  "--use-pep517",
858
859
  dest="use_pep517",
859
860
  action="store_true",
860
- default=None,
861
- help="Use PEP 517 for building source distributions "
862
- "(use --no-use-pep517 to force legacy behaviour).",
863
- )
864
-
865
- no_use_pep517: Any = partial(
866
- Option,
867
- "--no-use-pep517",
868
- dest="use_pep517",
869
- action="callback",
870
- callback=_handle_no_use_pep517,
871
- default=None,
861
+ default=True,
872
862
  help=SUPPRESS_HELP,
873
863
  )
874
864
 
@@ -901,30 +891,11 @@ config_settings: Callable[..., Option] = partial(
901
891
  action="callback",
902
892
  callback=_handle_config_settings,
903
893
  metavar="settings",
904
- help="Configuration settings to be passed to the PEP 517 build backend. "
894
+ help="Configuration settings to be passed to the build backend. "
905
895
  "Settings take the form KEY=VALUE. Use multiple --config-settings options "
906
896
  "to pass multiple keys to the backend.",
907
897
  )
908
898
 
909
- build_options: Callable[..., Option] = partial(
910
- Option,
911
- "--build-option",
912
- dest="build_options",
913
- metavar="options",
914
- action="append",
915
- help="Extra arguments to be supplied to 'setup.py bdist_wheel'.",
916
- )
917
-
918
- global_options: Callable[..., Option] = partial(
919
- Option,
920
- "--global-option",
921
- dest="global_options",
922
- action="append",
923
- metavar="options",
924
- help="Extra global options to be supplied to the setup.py "
925
- "call before the install or bdist_wheel command.",
926
- )
927
-
928
899
  no_clean: Callable[..., Option] = partial(
929
900
  Option,
930
901
  "--no-clean",
@@ -1072,6 +1043,7 @@ use_new_feature: Callable[..., Option] = partial(
1072
1043
  default=[],
1073
1044
  choices=[
1074
1045
  "fast-deps",
1046
+ "build-constraint",
1075
1047
  ]
1076
1048
  + ALWAYS_ENABLED_FEATURES,
1077
1049
  help="Enable new functionality, that may be backward incompatible.",
@@ -203,9 +203,9 @@ class ConfigOptionParser(CustomOptionParser):
203
203
  if section in override_order:
204
204
  section_items[section].append((key, val))
205
205
 
206
- # Yield each group in their override order
207
- for section in override_order:
208
- yield from section_items[section]
206
+ # Yield each group in their override order
207
+ for section in override_order:
208
+ yield from section_items[section]
209
209
 
210
210
  def _update_defaults(self, defaults: dict[str, Any]) -> dict[str, Any]:
211
211
  """Updates the given defaults with values from the config files and
@@ -8,9 +8,10 @@ PackageFinder machinery and all its vendored dependencies, etc.
8
8
  from __future__ import annotations
9
9
 
10
10
  import logging
11
+ import os
11
12
  from functools import partial
12
13
  from optparse import Values
13
- from typing import Any
14
+ from typing import Any, Callable, TypeVar
14
15
 
15
16
  from pip._internal.build_env import SubprocessBuildEnvironmentInstaller
16
17
  from pip._internal.cache import WheelCache
@@ -44,6 +45,16 @@ from pip._internal.utils.temp_dir import (
44
45
  logger = logging.getLogger(__name__)
45
46
 
46
47
 
48
+ def should_ignore_regular_constraints(options: Values) -> bool:
49
+ """
50
+ Check if regular constraints should be ignored because
51
+ we are in a isolated build process and build constraints
52
+ feature is enabled but no build constraints were passed.
53
+ """
54
+
55
+ return os.environ.get("_PIP_IN_BUILD_IGNORE_CONSTRAINTS") == "1"
56
+
57
+
47
58
  KEEPABLE_TEMPDIR_TYPES = [
48
59
  tempdir_kinds.BUILD_ENV,
49
60
  tempdir_kinds.EPHEM_WHEEL_CACHE,
@@ -51,7 +62,12 @@ KEEPABLE_TEMPDIR_TYPES = [
51
62
  ]
52
63
 
53
64
 
54
- def with_cleanup(func: Any) -> Any:
65
+ _CommandT = TypeVar("_CommandT", bound="RequirementCommand")
66
+
67
+
68
+ def with_cleanup(
69
+ func: Callable[[_CommandT, Values, list[str]], int],
70
+ ) -> Callable[[_CommandT, Values, list[str]], int]:
55
71
  """Decorator for common logic related to managing temporary
56
72
  directories.
57
73
  """
@@ -60,9 +76,7 @@ def with_cleanup(func: Any) -> Any:
60
76
  for t in KEEPABLE_TEMPDIR_TYPES:
61
77
  registry.set_delete(t, False)
62
78
 
63
- def wrapper(
64
- self: RequirementCommand, options: Values, args: list[Any]
65
- ) -> int | None:
79
+ def wrapper(self: _CommandT, options: Values, args: list[str]) -> int:
66
80
  assert self.tempdir_registry is not None
67
81
  if options.no_clean:
68
82
  configure_tempdir_registry(self.tempdir_registry)
@@ -132,12 +146,22 @@ class RequirementCommand(IndexGroupCommand):
132
146
  "fast-deps has no effect when used with the legacy resolver."
133
147
  )
134
148
 
149
+ # Handle build constraints
150
+ build_constraints = getattr(options, "build_constraints", [])
151
+ build_constraint_feature_enabled = (
152
+ "build-constraint" in options.features_enabled
153
+ )
154
+
135
155
  return RequirementPreparer(
136
156
  build_dir=temp_build_dir_path,
137
157
  src_dir=options.src_dir,
138
158
  download_dir=download_dir,
139
159
  build_isolation=options.build_isolation,
140
- build_isolation_installer=SubprocessBuildEnvironmentInstaller(finder),
160
+ build_isolation_installer=SubprocessBuildEnvironmentInstaller(
161
+ finder,
162
+ build_constraints=build_constraints,
163
+ build_constraint_feature_enabled=build_constraint_feature_enabled,
164
+ ),
141
165
  check_build_deps=options.check_build_deps,
142
166
  build_tracker=build_tracker,
143
167
  session=session,
@@ -163,7 +187,6 @@ class RequirementCommand(IndexGroupCommand):
163
187
  ignore_requires_python: bool = False,
164
188
  force_reinstall: bool = False,
165
189
  upgrade_strategy: str = "to-satisfy-only",
166
- use_pep517: bool | None = None,
167
190
  py_version_info: tuple[int, ...] | None = None,
168
191
  ) -> BaseResolver:
169
192
  """
@@ -172,7 +195,6 @@ class RequirementCommand(IndexGroupCommand):
172
195
  make_install_req = partial(
173
196
  install_req_from_req_string,
174
197
  isolated=options.isolated_mode,
175
- use_pep517=use_pep517,
176
198
  )
177
199
  resolver_variant = cls.determine_resolver_variant(options)
178
200
  # The long import name and duplicated invocation is needed to convince
@@ -221,27 +243,28 @@ class RequirementCommand(IndexGroupCommand):
221
243
  Parse command-line arguments into the corresponding requirements.
222
244
  """
223
245
  requirements: list[InstallRequirement] = []
224
- for filename in options.constraints:
225
- for parsed_req in parse_requirements(
226
- filename,
227
- constraint=True,
228
- finder=finder,
229
- options=options,
230
- session=session,
231
- ):
232
- req_to_add = install_req_from_parsed_requirement(
233
- parsed_req,
234
- isolated=options.isolated_mode,
235
- user_supplied=False,
236
- )
237
- requirements.append(req_to_add)
246
+
247
+ if not should_ignore_regular_constraints(options):
248
+ for filename in options.constraints:
249
+ for parsed_req in parse_requirements(
250
+ filename,
251
+ constraint=True,
252
+ finder=finder,
253
+ options=options,
254
+ session=session,
255
+ ):
256
+ req_to_add = install_req_from_parsed_requirement(
257
+ parsed_req,
258
+ isolated=options.isolated_mode,
259
+ user_supplied=False,
260
+ )
261
+ requirements.append(req_to_add)
238
262
 
239
263
  for req in args:
240
264
  req_to_add = install_req_from_line(
241
265
  req,
242
266
  comes_from=None,
243
267
  isolated=options.isolated_mode,
244
- use_pep517=options.use_pep517,
245
268
  user_supplied=True,
246
269
  config_settings=getattr(options, "config_settings", None),
247
270
  )
@@ -252,7 +275,6 @@ class RequirementCommand(IndexGroupCommand):
252
275
  req_to_add = install_req_from_req_string(
253
276
  req,
254
277
  isolated=options.isolated_mode,
255
- use_pep517=options.use_pep517,
256
278
  user_supplied=True,
257
279
  )
258
280
  requirements.append(req_to_add)
@@ -262,7 +284,6 @@ class RequirementCommand(IndexGroupCommand):
262
284
  req,
263
285
  user_supplied=True,
264
286
  isolated=options.isolated_mode,
265
- use_pep517=options.use_pep517,
266
287
  config_settings=getattr(options, "config_settings", None),
267
288
  )
268
289
  requirements.append(req_to_add)
@@ -275,7 +296,6 @@ class RequirementCommand(IndexGroupCommand):
275
296
  req_to_add = install_req_from_parsed_requirement(
276
297
  parsed_req,
277
298
  isolated=options.isolated_mode,
278
- use_pep517=options.use_pep517,
279
299
  user_supplied=True,
280
300
  config_settings=(
281
301
  parsed_req.options.get("config_settings")
@@ -7,7 +7,6 @@ from pip._internal.cli.cmdoptions import make_target_python
7
7
  from pip._internal.cli.req_command import RequirementCommand, with_cleanup
8
8
  from pip._internal.cli.status_codes import SUCCESS
9
9
  from pip._internal.operations.build.build_tracker import get_build_tracker
10
- from pip._internal.req.req_install import check_legacy_setup_py_options
11
10
  from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
12
11
  from pip._internal.utils.temp_dir import TempDirectory
13
12
 
@@ -36,9 +35,9 @@ class DownloadCommand(RequirementCommand):
36
35
 
37
36
  def add_options(self) -> None:
38
37
  self.cmd_opts.add_option(cmdoptions.constraints())
38
+ self.cmd_opts.add_option(cmdoptions.build_constraints())
39
39
  self.cmd_opts.add_option(cmdoptions.requirements())
40
40
  self.cmd_opts.add_option(cmdoptions.no_deps())
41
- self.cmd_opts.add_option(cmdoptions.global_options())
42
41
  self.cmd_opts.add_option(cmdoptions.no_binary())
43
42
  self.cmd_opts.add_option(cmdoptions.only_binary())
44
43
  self.cmd_opts.add_option(cmdoptions.prefer_binary())
@@ -48,7 +47,6 @@ class DownloadCommand(RequirementCommand):
48
47
  self.cmd_opts.add_option(cmdoptions.progress_bar())
49
48
  self.cmd_opts.add_option(cmdoptions.no_build_isolation())
50
49
  self.cmd_opts.add_option(cmdoptions.use_pep517())
51
- self.cmd_opts.add_option(cmdoptions.no_use_pep517())
52
50
  self.cmd_opts.add_option(cmdoptions.check_build_deps())
53
51
  self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
54
52
 
@@ -81,6 +79,7 @@ class DownloadCommand(RequirementCommand):
81
79
  options.editables = []
82
80
 
83
81
  cmdoptions.check_dist_restriction(options)
82
+ cmdoptions.check_build_constraints(options)
84
83
 
85
84
  options.download_dir = normalize_path(options.download_dir)
86
85
  ensure_dir(options.download_dir)
@@ -104,7 +103,6 @@ class DownloadCommand(RequirementCommand):
104
103
  )
105
104
 
106
105
  reqs = self.get_requirements(args, options, finder, session)
107
- check_legacy_setup_py_options(options, reqs)
108
106
 
109
107
  preparer = self.make_requirement_preparer(
110
108
  temp_build_dir=directory,
@@ -122,7 +120,6 @@ class DownloadCommand(RequirementCommand):
122
120
  finder=finder,
123
121
  options=options,
124
122
  ignore_requires_python=options.ignore_requires_python,
125
- use_pep517=options.use_pep517,
126
123
  py_version_info=options.python_version,
127
124
  )
128
125
 
@@ -130,6 +127,8 @@ class DownloadCommand(RequirementCommand):
130
127
 
131
128
  requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
132
129
 
130
+ preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
131
+
133
132
  downloaded: list[str] = []
134
133
  for req in requirement_set.requirements.values():
135
134
  if req.satisfied_by is None:
@@ -137,8 +136,6 @@ class DownloadCommand(RequirementCommand):
137
136
  preparer.save_linked_requirement(req)
138
137
  downloaded.append(req.name)
139
138
 
140
- preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
141
-
142
139
  if downloaded:
143
140
  write_output("Successfully downloaded %s", " ".join(downloaded))
144
141
 
@@ -41,7 +41,6 @@ from pip._internal.operations.check import ConflictDetails, check_install_confli
41
41
  from pip._internal.req import install_given_reqs
42
42
  from pip._internal.req.req_install import (
43
43
  InstallRequirement,
44
- check_legacy_setup_py_options,
45
44
  )
46
45
  from pip._internal.utils.compat import WINDOWS
47
46
  from pip._internal.utils.filesystem import test_writable_dir
@@ -59,7 +58,7 @@ from pip._internal.utils.virtualenv import (
59
58
  running_under_virtualenv,
60
59
  virtualenv_no_global,
61
60
  )
62
- from pip._internal.wheel_builder import build, should_build_for_install_command
61
+ from pip._internal.wheel_builder import build
63
62
 
64
63
  logger = getLogger(__name__)
65
64
 
@@ -87,6 +86,7 @@ class InstallCommand(RequirementCommand):
87
86
  def add_options(self) -> None:
88
87
  self.cmd_opts.add_option(cmdoptions.requirements())
89
88
  self.cmd_opts.add_option(cmdoptions.constraints())
89
+ self.cmd_opts.add_option(cmdoptions.build_constraints())
90
90
  self.cmd_opts.add_option(cmdoptions.no_deps())
91
91
  self.cmd_opts.add_option(cmdoptions.pre())
92
92
 
@@ -210,12 +210,10 @@ class InstallCommand(RequirementCommand):
210
210
  self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
211
211
  self.cmd_opts.add_option(cmdoptions.no_build_isolation())
212
212
  self.cmd_opts.add_option(cmdoptions.use_pep517())
213
- self.cmd_opts.add_option(cmdoptions.no_use_pep517())
214
213
  self.cmd_opts.add_option(cmdoptions.check_build_deps())
215
214
  self.cmd_opts.add_option(cmdoptions.override_externally_managed())
216
215
 
217
216
  self.cmd_opts.add_option(cmdoptions.config_settings())
218
- self.cmd_opts.add_option(cmdoptions.global_options())
219
217
 
220
218
  self.cmd_opts.add_option(
221
219
  "--compile",
@@ -303,6 +301,7 @@ class InstallCommand(RequirementCommand):
303
301
  if options.upgrade:
304
302
  upgrade_strategy = options.upgrade_strategy
305
303
 
304
+ cmdoptions.check_build_constraints(options)
306
305
  cmdoptions.check_dist_restriction(options, check_target=True)
307
306
 
308
307
  logger.verbose("Using %s", get_pip_version())
@@ -334,8 +333,6 @@ class InstallCommand(RequirementCommand):
334
333
  target_temp_dir_path = target_temp_dir.path
335
334
  self.enter_context(target_temp_dir)
336
335
 
337
- global_options = options.global_options or []
338
-
339
336
  session = self.get_default_session(options)
340
337
 
341
338
  target_python = make_target_python(options)
@@ -355,7 +352,6 @@ class InstallCommand(RequirementCommand):
355
352
 
356
353
  try:
357
354
  reqs = self.get_requirements(args, options, finder, session)
358
- check_legacy_setup_py_options(options, reqs)
359
355
 
360
356
  wheel_cache = WheelCache(options.cache_dir)
361
357
 
@@ -384,7 +380,6 @@ class InstallCommand(RequirementCommand):
384
380
  ignore_requires_python=options.ignore_requires_python,
385
381
  force_reinstall=options.force_reinstall,
386
382
  upgrade_strategy=upgrade_strategy,
387
- use_pep517=options.use_pep517,
388
383
  py_version_info=options.python_version,
389
384
  )
390
385
 
@@ -414,6 +409,13 @@ class InstallCommand(RequirementCommand):
414
409
  )
415
410
  return SUCCESS
416
411
 
412
+ # If there is any more preparation to do for the actual installation, do
413
+ # so now. This includes actually downloading the files in the case that
414
+ # we have been using PEP-658 metadata so far.
415
+ preparer.prepare_linked_requirements_more(
416
+ requirement_set.requirements.values()
417
+ )
418
+
417
419
  try:
418
420
  pip_req = requirement_set.get_requirement("pip")
419
421
  except KeyError:
@@ -425,17 +427,13 @@ class InstallCommand(RequirementCommand):
425
427
  protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)
426
428
 
427
429
  reqs_to_build = [
428
- r
429
- for r in requirement_set.requirements_to_install
430
- if should_build_for_install_command(r)
430
+ r for r in requirement_set.requirements_to_install if not r.is_wheel
431
431
  ]
432
432
 
433
433
  _, build_failures = build(
434
434
  reqs_to_build,
435
435
  wheel_cache=wheel_cache,
436
436
  verify=True,
437
- build_options=[],
438
- global_options=global_options,
439
437
  )
440
438
 
441
439
  if build_failures:
@@ -459,7 +457,6 @@ class InstallCommand(RequirementCommand):
459
457
 
460
458
  installed = install_given_reqs(
461
459
  to_install,
462
- global_options,
463
460
  root=options.root_path,
464
461
  home=target_temp_dir_path,
465
462
  prefix=options.prefix_path,
@@ -690,6 +687,7 @@ def decide_user_install(
690
687
  logger.debug("Non-user install by explicit request")
691
688
  return False
692
689
 
690
+ # If we have been asked for a user install explicitly, check compatibility.
693
691
  if use_user_site:
694
692
  if prefix_path:
695
693
  raise CommandError(
@@ -701,6 +699,13 @@ def decide_user_install(
701
699
  "Can not perform a '--user' install. User site-packages "
702
700
  "are not visible in this virtualenv."
703
701
  )
702
+ # Catch all remaining cases which honour the site.ENABLE_USER_SITE
703
+ # value, such as a plain Python installation (e.g. no virtualenv).
704
+ if not site.ENABLE_USER_SITE:
705
+ raise InstallationError(
706
+ "Can not perform a '--user' install. User site-packages "
707
+ "are disabled for this Python."
708
+ )
704
709
  logger.debug("User install by explicit request")
705
710
  return True
706
711