Skip to content
Closed

AI junk #3646

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ Unreleased
stream when no external pager runs, completing the partial
`I/O operation on closed file` fix from {pr}`3482`. {issue}`3449`
{pr}`3533`
- `confirm` and `prompt` strip ANSI style codes from the prompt text when
the output stream is not a terminal, restoring the pre-`8.4.0` behavior
so styled prompts match `echo` under `CliRunner` and redirected output.
{issue}`3572` {pr}`3646`

## Version 8.4.1

Expand Down
18 changes: 18 additions & 0 deletions src/click/termui.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
from contextlib import redirect_stdout
from gettext import gettext as _

from ._compat import _default_text_stderr
from ._compat import _default_text_stdout
from ._compat import isatty
from ._compat import should_strip_ansi
from ._compat import strip_ansi
from .exceptions import Abort
from .exceptions import UsageError
Expand Down Expand Up @@ -83,7 +86,14 @@ def hidden_prompt_func(prompt: str) -> str:
def _readline_prompt(func: t.Callable[[str], str], text: str, err: bool) -> str:
"""Call a prompt function, passing the full prompt on non-Windows so
readline can handle line editing and cursor positioning correctly.

The prompt is written by the prompt function rather than :func:`echo`,
so strip ANSI style codes here when the target stream is not a
terminal, matching :func:`echo`'s behavior.
"""
stream = _default_text_stderr() if err else _default_text_stdout()
if should_strip_ansi(stream, resolve_color_default()):
text = strip_ansi(text)
if err:
with redirect_stdout(sys.stderr):
return func(text)
Expand Down Expand Up @@ -156,6 +166,10 @@ def prompt(
show_choices is true and text is "Group by" then the
prompt will be "Group by (day, week): ".

.. versionchanged:: 8.4.2
ANSI style codes are stripped from the prompt when the output
stream is not a terminal, matching ``echo``.

.. versionchanged:: 8.3.3
``show_default`` can be a string to show a custom value instead
of the actual default, matching the help text behavior.
Expand Down Expand Up @@ -251,6 +265,10 @@ def confirm(
:param err: if set to true the file defaults to ``stderr`` instead of
``stdout``, the same as with echo.

.. versionchanged:: 8.4.2
ANSI style codes are stripped from the prompt when the output
stream is not a terminal, matching ``echo``.

.. versionchanged:: 8.3.1
A space is no longer appended to the prompt.

Expand Down
27 changes: 27 additions & 0 deletions tests/test_termui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1560,3 +1560,30 @@ def cli():
result = runner.invoke(cli, input="leaky\n", mix_stderr=False)
assert "leaky" not in result.stdout
assert "leaky" not in result.stderr


def test_confirm_strips_ansi_when_color_disabled(runner):
"""``click.confirm`` writes its prompt through a non-tty stream under
``CliRunner``. ANSI style codes must be stripped from that prompt, the
same way :func:`click.echo` strips them, so output matches what users
saw before the readline change in 8.4.0 (see issue #3572).
"""

@click.command()
def cli():
click.confirm(click.style("Continue", fg="green"), default=True)

result = runner.invoke(cli, input="y\n", color=False)
assert result.output == "Continue [Y/n]: y\n"


def test_prompt_strips_ansi_when_color_disabled(runner):
"""``click.prompt`` must also strip ANSI codes from its prompt text
when the output stream is not a terminal (issue #3572)."""

@click.command()
def cli():
click.prompt(click.style("Name", fg="green"))

result = runner.invoke(cli, input="click\n", color=False)
assert result.output == "Name: click\n"
Loading