From 0e908527969fdad0979a35d0d02f4b8729d6294d Mon Sep 17 00:00:00 2001 From: Oaksprout Date: Fri, 13 Mar 2026 18:17:48 +0000 Subject: [PATCH] Fix show_default string not displayed in prompts When show_default is set to a custom string on an option with prompt=True, the prompt now displays that string instead of the actual default value, matching the behavior already present in help text. Fixes #2836 --- src/click/core.py | 6 +++--- src/click/termui.py | 9 ++++++--- tests/test_termui.py | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/click/core.py b/src/click/core.py index 6adc65ccd6..51492690c5 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -3145,10 +3145,10 @@ def prompt_for_value(self, ctx: Context) -> t.Any: default = bool(default) return confirm(self.prompt, default) - # If show_default is set to True/False, provide this to `prompt` as well. For - # non-bool values of `show_default`, we use `prompt`'s default behavior + # Pass show_default to prompt. When it's a string, the prompt will + # display that string instead of the actual default value. prompt_kwargs: t.Any = {} - if isinstance(self.show_default, bool): + if self.show_default is not None: prompt_kwargs["show_default"] = self.show_default return prompt( diff --git a/src/click/termui.py b/src/click/termui.py index 2e98a0771c..fca119dd1c 100644 --- a/src/click/termui.py +++ b/src/click/termui.py @@ -60,7 +60,7 @@ def hidden_prompt_func(prompt: str) -> str: def _build_prompt( text: str, suffix: str, - show_default: bool = False, + show_default: bool | str = False, default: t.Any | None = None, show_choices: bool = True, type: ParamType | None = None, @@ -69,7 +69,10 @@ def _build_prompt( if type is not None and show_choices and isinstance(type, Choice): prompt += f" ({', '.join(map(str, type.choices))})" if default is not None and show_default: - prompt = f"{prompt} [{_format_default(default)}]" + if isinstance(show_default, str): + prompt = f"{prompt} [{show_default}]" + else: + prompt = f"{prompt} [{_format_default(default)}]" return f"{prompt}{suffix}" @@ -88,7 +91,7 @@ def prompt( type: ParamType | t.Any | None = None, value_proc: t.Callable[[str], t.Any] | None = None, prompt_suffix: str = ": ", - show_default: bool = True, + show_default: bool | str = True, err: bool = False, show_choices: bool = True, ) -> t.Any: diff --git a/tests/test_termui.py b/tests/test_termui.py index 8220431bb4..a2e9e2f84d 100644 --- a/tests/test_termui.py +++ b/tests/test_termui.py @@ -710,3 +710,22 @@ def cli(flag): assert result.output == expected_output assert not result.stderr assert result.exit_code == 0 if expected not in (REPEAT, INVALID) else 1 + + +def test_string_show_default_in_prompt(runner): + """When show_default is a string, the prompt should display that string + instead of the actual default value. See pallets/click#2836.""" + + @click.command() + @click.option( + "--name", + default="actual_default", + show_default="custom label", + prompt=True, + ) + def cmd(name): + click.echo(name) + + result = runner.invoke(cmd, input="\n", standalone_mode=False) + assert "custom label" in result.output + assert "actual_default" not in result.output.split("\n")[0]