Skip to content

Commit 4fd2fea

Browse files
kieranyyunherbert25
andcommitted
Fix condition for setting flag value when type is provided
Co-authored-by: Nate Herbert <[email protected]>
1 parent 9ce34f2 commit 4fd2fea

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
Version 8.2.1
44
-------------
55

6+
- Fix flag value handling for flag options with a provided type. :issue:`2894`
7+
:issue:`2897` :pr:`2930`
68

79
Version 8.2.0
810
-------------

src/click/core.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,10 +2610,11 @@ def __init__(
26102610
else:
26112611
self.default = False
26122612

2613+
if is_flag and flag_value is None:
2614+
flag_value = not self.default
2615+
26132616
self.type: types.ParamType
26142617
if is_flag and type is None:
2615-
if flag_value is None:
2616-
flag_value = not self.default
26172618
# Re-guess the type from the flag value instead of the
26182619
# default.
26192620
self.type = types.convert_type(None, flag_value)

tests/test_options.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,31 @@ def test_type_from_flag_value():
10071007
assert param.type is click.INT
10081008

10091009

1010+
@pytest.mark.parametrize(
1011+
("opts", "pass_flag", "expected"),
1012+
[
1013+
pytest.param({"type": bool}, False, "False"),
1014+
pytest.param({"type": bool}, True, "True"),
1015+
pytest.param({"type": bool, "default": True}, False, "True"),
1016+
pytest.param({"type": bool, "default": True}, True, "False"),
1017+
pytest.param({"type": click.BOOL}, False, "False"),
1018+
pytest.param({"type": click.BOOL}, True, "True"),
1019+
pytest.param({"type": click.BOOL, "default": True}, False, "True"),
1020+
pytest.param({"type": click.BOOL, "default": True}, True, "False"),
1021+
pytest.param({"type": str}, False, ""),
1022+
pytest.param({"type": str}, True, "True"),
1023+
],
1024+
)
1025+
def test_flag_value_is_correctly_set(runner, opts, pass_flag, expected):
1026+
@click.command()
1027+
@click.option("--foo", is_flag=True, **opts)
1028+
def cmd(foo):
1029+
click.echo(foo)
1030+
1031+
result = runner.invoke(cmd, ["--foo"] if pass_flag else [])
1032+
assert result.output == f"{expected}\n"
1033+
1034+
10101035
@pytest.mark.parametrize(
10111036
("option", "expected"),
10121037
[
@@ -1040,6 +1065,20 @@ def test_invalid_flag_combinations(runner, kwargs, message):
10401065
assert message in str(e.value)
10411066

10421067

1068+
def test_non_flag_with_non_negatable_default(runner):
1069+
class NonNegatable:
1070+
def __bool__(self):
1071+
raise ValueError("Cannot negate this object")
1072+
1073+
@click.command()
1074+
@click.option("--foo", default=NonNegatable())
1075+
def cmd(foo):
1076+
pass
1077+
1078+
result = runner.invoke(cmd)
1079+
assert result.exit_code == 0
1080+
1081+
10431082
@pytest.mark.parametrize(
10441083
("choices", "metavars"),
10451084
[

0 commit comments

Comments
 (0)