From 8f620405e3b3aab543e17cf12b8abee9becb7fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Fri, 10 Mar 2023 10:55:49 +0000 Subject: [PATCH] Support passing the same key multiple times in --config-settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe LaĆ­ns --- news/11681.feature.rst | 4 ++++ src/pip/_internal/cli/cmdoptions.py | 8 +++++++- tests/unit/test_pyproject_config.py | 15 ++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 news/11681.feature.rst diff --git a/news/11681.feature.rst b/news/11681.feature.rst new file mode 100644 index 00000000000..a0d918b19f9 --- /dev/null +++ b/news/11681.feature.rst @@ -0,0 +1,4 @@ +The ``--config-settings``/``-C`` option now supports using the same key multiple +times. When the same key is specified multiple times, all values are passed to +the build backend as a list, as opposed to the previous behavior where pip would +only pass the last value is the same key was used multiple times. diff --git a/src/pip/_internal/cli/cmdoptions.py b/src/pip/_internal/cli/cmdoptions.py index 6a33cf48dc5..d7d6df00981 100644 --- a/src/pip/_internal/cli/cmdoptions.py +++ b/src/pip/_internal/cli/cmdoptions.py @@ -811,7 +811,13 @@ def _handle_config_settings( if dest is None: dest = {} setattr(parser.values, option.dest, dest) - dest[key] = val + if key in dest: + if isinstance(dest[key], list): + dest[key].append(val) + else: + dest[key] = [dest[key], val] + else: + dest[key] = val config_settings: Callable[..., Option] = partial( diff --git a/tests/unit/test_pyproject_config.py b/tests/unit/test_pyproject_config.py index 9937f3880aa..c7e46956055 100644 --- a/tests/unit/test_pyproject_config.py +++ b/tests/unit/test_pyproject_config.py @@ -1,3 +1,5 @@ +from typing import Dict, List + import pytest from pip._internal.commands import create_command @@ -36,9 +38,16 @@ def test_set_config_empty_value() -> None: assert options.config_settings == {"x": ""} -def test_replace_config_value() -> None: +@pytest.mark.parametrize( + ("passed", "expected"), + [ + (["x=hello", "x=world"], {"x": ["hello", "world"]}), + (["x=hello", "x=world", "x=other"], {"x": ["hello", "world", "other"]}), + ], +) +def test_multiple_config_values(passed: List[str], expected: Dict[str, str]) -> None: i = create_command("install") options, _ = i.parse_args( - ["xxx", "--config-settings", "x=hello", "--config-settings", "x=world"] + ["xxx", *(f"--config-settings={option}" for option in passed)] ) - assert options.config_settings == {"x": "world"} + assert options.config_settings == expected