Skip to content

Commit cdeb8f9

Browse files
authored
Merge pull request #11059 from pfmoore/config_settings
Add a UI to set config settings for PEP 517 backends
2 parents 6313d86 + 437bb67 commit cdeb8f9

File tree

13 files changed

+336
-1
lines changed

13 files changed

+336
-1
lines changed

docs/html/reference/build-system/pyproject-toml.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ This is considered a stopgap solution until setuptools adds support for
106106
regular {ref}`deprecation policy <Deprecation Policy>`.
107107
```
108108

109+
### Backend Configuration
110+
111+
Build backends have the ability to accept configuration settings, which can
112+
change the way the build is handled. These settings take the form of a
113+
series of `key=value` pairs. The user can supply configuration settings
114+
using the `--config-settings` command line option (which can be supplied
115+
multiple times, in order to specify multiple settings).
116+
117+
The supplied configuration settings are passed to every backend hook call.
118+
109119
## Build output
110120

111121
It is the responsibility of the build backend to ensure that the output is

docs/html/reference/requirements-file-format.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ The options which can be applied to individual requirements are:
111111

112112
- {ref}`--install-option <install_--install-option>`
113113
- {ref}`--global-option <install_--global-option>`
114+
- {ref}`--config-settings <install_--config-settings>`
114115
- `--hash` (for {ref}`Hash-checking mode`)
115116

116117
## Referring to other requirements files

news/11059.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add a user interface for supplying config settings to build backends.

src/pip/_internal/cli/cmdoptions.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,33 @@ def _handle_no_use_pep517(
801801
help=SUPPRESS_HELP,
802802
)
803803

804+
805+
def _handle_config_settings(
806+
option: Option, opt_str: str, value: str, parser: OptionParser
807+
) -> None:
808+
key, sep, val = value.partition("=")
809+
if sep != "=":
810+
parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa
811+
dest = getattr(parser.values, option.dest)
812+
if dest is None:
813+
dest = {}
814+
setattr(parser.values, option.dest, dest)
815+
dest[key] = val
816+
817+
818+
config_settings: Callable[..., Option] = partial(
819+
Option,
820+
"--config-settings",
821+
dest="config_settings",
822+
type=str,
823+
action="callback",
824+
callback=_handle_config_settings,
825+
metavar="settings",
826+
help="Configuration settings to be passed to the PEP 517 build backend. "
827+
"Settings take the form KEY=VALUE. Use multiple --config-settings options "
828+
"to pass multiple keys to the backend.",
829+
)
830+
804831
install_options: Callable[..., Option] = partial(
805832
Option,
806833
"--install-option",

src/pip/_internal/cli/req_command.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ def make_resolver(
325325
install_req_from_req_string,
326326
isolated=options.isolated_mode,
327327
use_pep517=use_pep517,
328+
config_settings=getattr(options, "config_settings", None),
328329
)
329330
suppress_build_failures = cls.determine_build_failure_suppression(options)
330331
resolver_variant = cls.determine_resolver_variant(options)
@@ -397,6 +398,7 @@ def get_requirements(
397398
isolated=options.isolated_mode,
398399
use_pep517=options.use_pep517,
399400
user_supplied=True,
401+
config_settings=getattr(options, "config_settings", None),
400402
)
401403
requirements.append(req_to_add)
402404

@@ -406,6 +408,7 @@ def get_requirements(
406408
user_supplied=True,
407409
isolated=options.isolated_mode,
408410
use_pep517=options.use_pep517,
411+
config_settings=getattr(options, "config_settings", None),
409412
)
410413
requirements.append(req_to_add)
411414

src/pip/_internal/commands/install.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ def add_options(self) -> None:
190190
self.cmd_opts.add_option(cmdoptions.use_pep517())
191191
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
192192

193+
self.cmd_opts.add_option(cmdoptions.config_settings())
193194
self.cmd_opts.add_option(cmdoptions.install_options())
194195
self.cmd_opts.add_option(cmdoptions.global_options())
195196

src/pip/_internal/commands/wheel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def add_options(self) -> None:
7373
help="Don't verify if built wheel is valid.",
7474
)
7575

76+
self.cmd_opts.add_option(cmdoptions.config_settings())
7677
self.cmd_opts.add_option(cmdoptions.build_options())
7778
self.cmd_opts.add_option(cmdoptions.global_options())
7879

src/pip/_internal/req/constructors.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ def install_req_from_editable(
207207
constraint: bool = False,
208208
user_supplied: bool = False,
209209
permit_editable_wheels: bool = False,
210+
config_settings: Optional[Dict[str, str]] = None,
210211
) -> InstallRequirement:
211212

212213
parts = parse_req_from_editable(editable_req)
@@ -224,6 +225,7 @@ def install_req_from_editable(
224225
install_options=options.get("install_options", []) if options else [],
225226
global_options=options.get("global_options", []) if options else [],
226227
hash_options=options.get("hashes", {}) if options else {},
228+
config_settings=config_settings,
227229
extras=parts.extras,
228230
)
229231

@@ -380,6 +382,7 @@ def install_req_from_line(
380382
constraint: bool = False,
381383
line_source: Optional[str] = None,
382384
user_supplied: bool = False,
385+
config_settings: Optional[Dict[str, str]] = None,
383386
) -> InstallRequirement:
384387
"""Creates an InstallRequirement from a name, which might be a
385388
requirement, directory containing 'setup.py', filename, or URL.
@@ -399,6 +402,7 @@ def install_req_from_line(
399402
install_options=options.get("install_options", []) if options else [],
400403
global_options=options.get("global_options", []) if options else [],
401404
hash_options=options.get("hashes", {}) if options else {},
405+
config_settings=config_settings,
402406
constraint=constraint,
403407
extras=parts.extras,
404408
user_supplied=user_supplied,
@@ -411,6 +415,7 @@ def install_req_from_req_string(
411415
isolated: bool = False,
412416
use_pep517: Optional[bool] = None,
413417
user_supplied: bool = False,
418+
config_settings: Optional[Dict[str, str]] = None,
414419
) -> InstallRequirement:
415420
try:
416421
req = get_requirement(req_string)
@@ -440,6 +445,7 @@ def install_req_from_req_string(
440445
isolated=isolated,
441446
use_pep517=use_pep517,
442447
user_supplied=user_supplied,
448+
config_settings=config_settings,
443449
)
444450

445451

@@ -448,6 +454,7 @@ def install_req_from_parsed_requirement(
448454
isolated: bool = False,
449455
use_pep517: Optional[bool] = None,
450456
user_supplied: bool = False,
457+
config_settings: Optional[Dict[str, str]] = None,
451458
) -> InstallRequirement:
452459
if parsed_req.is_editable:
453460
req = install_req_from_editable(
@@ -457,6 +464,7 @@ def install_req_from_parsed_requirement(
457464
constraint=parsed_req.constraint,
458465
isolated=isolated,
459466
user_supplied=user_supplied,
467+
config_settings=config_settings,
460468
)
461469

462470
else:
@@ -469,6 +477,7 @@ def install_req_from_parsed_requirement(
469477
constraint=parsed_req.constraint,
470478
line_source=parsed_req.line_source,
471479
user_supplied=user_supplied,
480+
config_settings=config_settings,
472481
)
473482
return req
474483

@@ -487,4 +496,5 @@ def install_req_from_link_and_ireq(
487496
install_options=ireq.install_options,
488497
global_options=ireq.global_options,
489498
hash_options=ireq.hash_options,
499+
config_settings=ireq.config_settings,
490500
)

src/pip/_internal/req/req_install.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
)
4747
from pip._internal.utils.hashes import Hashes
4848
from pip._internal.utils.misc import (
49+
ConfiguredPep517HookCaller,
4950
ask_path_exists,
5051
backup_dir,
5152
display_path,
@@ -80,6 +81,7 @@ def __init__(
8081
install_options: Optional[List[str]] = None,
8182
global_options: Optional[List[str]] = None,
8283
hash_options: Optional[Dict[str, List[str]]] = None,
84+
config_settings: Optional[Dict[str, str]] = None,
8385
constraint: bool = False,
8486
extras: Collection[str] = (),
8587
user_supplied: bool = False,
@@ -138,6 +140,7 @@ def __init__(
138140
self.install_options = install_options if install_options else []
139141
self.global_options = global_options if global_options else []
140142
self.hash_options = hash_options if hash_options else {}
143+
self.config_settings = config_settings
141144
# Set to True after successful preparation of this requirement
142145
self.prepared = False
143146
# User supplied requirement are explicitly requested for installation
@@ -469,7 +472,8 @@ def load_pyproject_toml(self) -> None:
469472
requires, backend, check, backend_path = pyproject_toml_data
470473
self.requirements_to_check = check
471474
self.pyproject_requires = requires
472-
self.pep517_backend = Pep517HookCaller(
475+
self.pep517_backend = ConfiguredPep517HookCaller(
476+
self,
473477
self.unpacked_source_directory,
474478
backend,
475479
backend_path=backend_path,

src/pip/_internal/resolution/resolvelib/candidates.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def make_install_req_from_link(
6969
global_options=template.global_options,
7070
hashes=template.hash_options,
7171
),
72+
config_settings=template.config_settings,
7273
)
7374
ireq.original_link = template.original_link
7475
ireq.link = link
@@ -92,6 +93,7 @@ def make_install_req_from_editable(
9293
global_options=template.global_options,
9394
hashes=template.hash_options,
9495
),
96+
config_settings=template.config_settings,
9597
)
9698

9799

@@ -116,6 +118,7 @@ def _make_install_req_from_dist(
116118
global_options=template.global_options,
117119
hashes=template.hash_options,
118120
),
121+
config_settings=template.config_settings,
119122
)
120123
ireq.satisfied_by = dist
121124
return ireq

0 commit comments

Comments
 (0)