Skip to content

Commit e2784dc

Browse files
committed
Split string values from default_map for multi-value parameters
Fixes #2745
1 parent f1f191e commit e2784dc

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ Unreleased
4040
- Change :class:`ParameterSource` to an :class:`~enum.IntEnum` and reorder
4141
its members from most to least explicit, so values can be compared to
4242
check whether a parameter was explicitly provided. :issue:`2879` :pr:`3248`
43+
- Split string values from ``default_map`` for parameters with ``nargs > 1``
44+
or :class:`Tuple` type, matching environment variable behavior.
45+
:issue:`2745`
4346

4447
Version 8.3.2
4548
-------------

src/click/core.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2356,6 +2356,11 @@ def consume_value(
23562356
value = default_map_value
23572357
source = ParameterSource.DEFAULT_MAP
23582358

2359+
# A string from default_map must be split for multi-value
2360+
# parameters, matching value_from_envvar behavior.
2361+
if isinstance(value, str) and self.nargs != 1:
2362+
value = self.type.split_envvar_value(value)
2363+
23592364
if value is UNSET:
23602365
default_value = self.get_default(ctx)
23612366
if default_value is not UNSET:

tests/test_defaults.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,38 @@ def cli(value):
357357
assert result.output == repr(expected)
358358

359359

360+
@pytest.mark.parametrize(
361+
("default_map", "option_kwargs", "cli_args", "expected"),
362+
[
363+
# String is split for nargs=2 option.
364+
({"point": "3 4"}, {"nargs": 2, "type": int}, [], (3, 4)),
365+
# String is split for explicit Tuple type.
366+
({"point": "hello world"}, {"type": (str, str)}, [], ("hello", "world")),
367+
# Already-structured tuple passes through unchanged.
368+
({"point": ("a", "b")}, {"nargs": 2}, [], ("a", "b")),
369+
# Already-structured list passes through unchanged.
370+
({"point": [5, 6]}, {"nargs": 2, "type": int}, [], (5, 6)),
371+
# CLI args override default_map for nargs > 1.
372+
({"point": "3 4"}, {"nargs": 2, "type": int}, ["--point", "10", "20"], (10, 20)),
373+
],
374+
)
375+
def test_default_map_nargs(runner, default_map, option_kwargs, cli_args, expected):
376+
"""A string in ``default_map`` for an option with ``nargs > 1`` should be
377+
split the same way an environment variable string is split.
378+
379+
Regression test for https://github.com/pallets/click/issues/2745.
380+
"""
381+
382+
@click.command()
383+
@click.option("--point", **option_kwargs)
384+
def cli(point):
385+
click.echo(repr(point))
386+
387+
result = runner.invoke(cli, cli_args, default_map=default_map)
388+
assert result.exit_code == 0
389+
assert result.output.strip() == repr(expected)
390+
391+
360392
def test_unset_in_default_map(runner):
361393
"""An ``UNSET`` value in ``default_map`` should be treated as if
362394
the key is absent, and so fallback to the parameter's own default.

0 commit comments

Comments
 (0)