Skip to content

Commit

Permalink
Allow options in config from both pip-compile and pip-sync (#1933)
Browse files Browse the repository at this point in the history
  • Loading branch information
atugushev committed Jul 26, 2023
1 parent 7386d28 commit d7885f8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 20 deletions.
54 changes: 34 additions & 20 deletions piptools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,36 +591,50 @@ def _validate_config(
:raises click.NoSuchOption: if config contains unknown keys.
:raises click.BadOptionUsage: if config contains invalid values.
"""
cli_params = {
param.name: param
for param in click_context.command.params
if param.name is not None
from piptools.scripts.compile import cli as compile_cli
from piptools.scripts.sync import cli as sync_cli

compile_cli_params = {
param.name: param for param in compile_cli.params if param.name is not None
}

sync_cli_params = {
param.name: param for param in sync_cli.params if param.name is not None
}

all_keys = set(compile_cli_params) | set(sync_cli_params)

for key, value in config.items():
# Validate unknown keys
if key not in cli_params:
possibilities = difflib.get_close_matches(key, cli_params.keys())
# Validate unknown keys in both compile and sync
if key not in all_keys:
possibilities = difflib.get_close_matches(key, all_keys)
raise click.NoSuchOption(
option_name=key,
message=f"No such config key {key!r}.",
possibilities=possibilities,
ctx=click_context,
)

# Validate invalid values
param = cli_params[key]
try:
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}.{os.linesep}"
f"Details: {e}"
),
ctx=click_context,
) from e
# Get all params associated with this key in both compile and sync
associated_params = (
cli_params[key]
for cli_params in (compile_cli_params, sync_cli_params)
if key in cli_params
)

# Validate value against types of all associated params
for param in associated_params:
try:
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}.{os.linesep}"
f"Details: {e}"
),
ctx=click_context,
) from e


def select_config_file(src_files: tuple[str, ...]) -> Path | None:
Expand Down
14 changes: 14 additions & 0 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3019,6 +3019,20 @@ def test_raise_error_on_invalid_config_option(
assert "Invalid value for config key 'dry_run': ['invalid', 'value']" in out.stderr


def test_allow_in_config_pip_sync_option(pip_conf, runner, tmp_path, make_config_file):
config_file = make_config_file("--ask", True) # pip-sync's option

req_in = tmp_path / "requirements.in"
req_in.touch()

out = runner.invoke(
cli, [req_in.as_posix(), "--verbose", "--config", config_file.as_posix()]
)

assert out.exit_code == 0
assert "Using pip-tools configuration defaults found" in out.stderr


def test_cli_boolean_flag_config_option_has_valid_context(
pip_conf, runner, tmp_path, make_config_file
):
Expand Down
13 changes: 13 additions & 0 deletions tests/test_cli_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,16 @@ def test_raise_error_on_invalid_config_option(run, runner, tmp_path, make_config

assert out.exit_code == 2
assert "Invalid value for config key 'dry_run': ['invalid', 'value']" in out.stderr


@mock.patch("piptools.sync.run")
def test_allow_in_config_pip_compile_option(run, runner, tmp_path, make_config_file):
config_file = make_config_file("generate-hashes", True) # pip-compile's option

with open(sync.DEFAULT_REQUIREMENTS_FILE, "w") as reqs_txt:
reqs_txt.write("six==1.10.0")

out = runner.invoke(cli, ["--verbose", "--config", config_file.as_posix()])

assert out.exit_code == 0
assert "Using pip-tools configuration defaults found" in out.stderr

0 comments on commit d7885f8

Please sign in to comment.