From 7386d28997c64db18b21c86caafc291b98cdbda2 Mon Sep 17 00:00:00 2001 From: Albert Tugushev Date: Tue, 25 Jul 2023 22:09:35 +0200 Subject: [PATCH] Refactor multi value options validation (#1915) --- piptools/utils.py | 27 +++++---------------------- tests/test_utils.py | 24 ++++++++++++++---------- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/piptools/utils.py b/piptools/utils.py index de2418473..a1711a507 100644 --- a/piptools/utils.py +++ b/piptools/utils.py @@ -611,11 +611,14 @@ def _validate_config( # Validate invalid values param = cli_params[key] try: - param.type.convert(value=value, param=param, ctx=click_context) + param.type_cast_value(value=value, ctx=click_context) except Exception as e: raise click.BadOptionUsage( option_name=key, - message=f"Invalid value for config key {key!r}: {value!r}.", + message=( + f"Invalid value for config key {key!r}: {value!r}.{os.linesep}" + f"Details: {e}" + ), ctx=click_context, ) from e @@ -662,17 +665,6 @@ def select_config_file(src_files: tuple[str, ...]) -> Path | None: } -# Ensure that any default overrides for these click options are lists, supporting multiple values -MULTIPLE_VALUE_OPTIONS = [ - "extras", - "upgrade_packages", - "unsafe_package", - "find_links", - "extra_index_url", - "trusted_host", -] - - def get_cli_options(ctx: click.Context) -> dict[str, click.Parameter]: cli_opts = { opt: option @@ -701,20 +693,11 @@ def parse_config_file( # In a TOML file, we expect the config to be under `[tool.pip-tools]` piptools_config: dict[str, Any] = config.get("tool", {}).get("pip-tools", {}) - piptools_config = _normalize_keys_in_config(piptools_config) piptools_config = _invert_negative_bool_options_in_config( ctx=click_context, config=piptools_config, ) - - # Any option with multiple values needs to be a list in the pyproject.toml - for mv_option in MULTIPLE_VALUE_OPTIONS: - if not isinstance(piptools_config.get(mv_option), (list, type(None))): - original_option = mv_option.replace("_", "-") - raise click.BadOptionUsage( - original_option, f"Config key '{original_option}' must be a list" - ) return piptools_config diff --git a/tests/test_utils.py b/tests/test_utils.py index 76ea0d612..7b3d7ead1 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -624,21 +624,25 @@ def test_callback_config_file_defaults(pyproject_param, new_default, make_config @pytest.mark.parametrize( - "mv_option", + ("param", "value"), ( - "extra", - "upgrade-package", - "unsafe-package", - "find-links", - "extra-index-url", - "trusted-host", + ("extra", "not-a-list"), + ("upgrade_package", "not-a-list"), + ("unsafe_package", "not-a-list"), + ("find_links", "not-a-list"), + ("extra_index_url", "not-a-list"), + ("trusted_host", "not-a-list"), + ("annotate", "not-a-bool"), + ("max_rounds", "not-an-int"), ), ) -def test_callback_config_file_defaults_multi_value_options(mv_option, make_config_file): - config_file = make_config_file(mv_option, "not-a-list") +def test_callback_config_file_defaults_multi_validate_value( + param, value, make_config_file +): + config_file = make_config_file(param, value) ctx = Context(compile_cli) ctx.params["src_files"] = (str(config_file),) - with pytest.raises(BadOptionUsage, match="must be a list"): + with pytest.raises(BadOptionUsage, match="Invalid value for config key"): override_defaults_from_config_file(ctx, "config", None)