Skip to content

Commit

Permalink
allow multiple=True with flags
Browse files Browse the repository at this point in the history
co-authored-by: Amethyst Reese <amethyst@n7.gg>
  • Loading branch information
davidism and amyreese committed Jul 3, 2023
1 parent d34d31f commit b36e3ed
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Unreleased
``standalone_mode`` is disabled. :issue:`2380`
- ``@group.command`` does not fail if the group was created with a custom
``command_class``. :issue:`2416`
- ``multiple=True`` is allowed for flag options again and does not require
setting ``default=()``. :issue:`2246, 2292, 2295`


Version 8.1.3
Expand Down
10 changes: 6 additions & 4 deletions src/click/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2570,8 +2570,13 @@ def __init__(
# flag if flag_value is set.
self._flag_needs_value = flag_value is not None

self.default: t.Union[t.Any, t.Callable[[], t.Any]]

if is_flag and default_is_missing and not self.required:
self.default: t.Union[t.Any, t.Callable[[], t.Any]] = False
if multiple:
self.default = ()
else:
self.default = False

if flag_value is None:
flag_value = not self.default
Expand Down Expand Up @@ -2622,9 +2627,6 @@ def __init__(
if self.is_flag:
raise TypeError("'count' is not valid with 'is_flag'.")

if self.multiple and self.is_flag:
raise TypeError("'multiple' is not valid with 'is_flag', use 'count'.")

def to_info_dict(self) -> t.Dict[str, t.Any]:
info_dict = super().to_info_dict()
info_dict.update(
Expand Down
21 changes: 21 additions & 0 deletions tests/test_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,24 @@ def cli(arg):
result = runner.invoke(cli, [])
assert not result.exception
assert result.output.splitlines() == ["<1|2>", "<3|4>"]


def test_multiple_flag_default(runner):
"""Default default for flags when multiple=True should be empty tuple."""

@click.command
# flag due to secondary token
@click.option("-y/-n", multiple=True)
# flag due to is_flag
@click.option("-f", is_flag=True, multiple=True)
# flag due to flag_value
@click.option("-v", "v", flag_value=1, multiple=True)
@click.option("-q", "v", flag_value=-1, multiple=True)
def cli(y, f, v):
return y, f, v

result = runner.invoke(cli, standalone_mode=False)
assert result.return_value == ((), (), ())

result = runner.invoke(cli, ["-y", "-n", "-f", "-v", "-q"], standalone_mode=False)
assert result.return_value == ((True, False), (True,), (1, -1))
4 changes: 0 additions & 4 deletions tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,10 +911,6 @@ def test_is_bool_flag_is_correctly_set(option, expected):
[
({"count": True, "multiple": True}, "'count' is not valid with 'multiple'."),
({"count": True, "is_flag": True}, "'count' is not valid with 'is_flag'."),
(
{"multiple": True, "is_flag": True},
"'multiple' is not valid with 'is_flag', use 'count'.",
),
],
)
def test_invalid_flag_combinations(runner, kwargs, message):
Expand Down

0 comments on commit b36e3ed

Please # to comment.