Repository: pallets/click (python)

Issue:
Click prompts do not cooperate with readline module
When readline is imported and a user presses backspace during a Click prompt, the entire prompt message is erased and cursor goes to beginning of the line. This can be reproduced with the following code:

```
import click, readline
click.prompt("Input")
```

This is due to [Python issue 12833](https://bugs.python.org/issue12833). The official recommendation is that the prompt should be displayed with raw_input. I noticed that Click first displays the prompt message using echo() and then uses raw_input("") for the prompt. There is also a workaround by passing " " to raw_input, however, that may be ugly in the display.


Pull request:
Fixed click.prompt not working with readline module
Applied the patch mentioned [here](https://github.com/pallets/click/issues/665#issuecomment-724643220). Seems to be working, I wasn't able to find out any immediate side-effects other than updating a couple of tests.

- fixes #665

Checklist:

- [x] Add or update relevant docs, in the docs folder and in code.
- [x] Add an entry in `CHANGES.rst` summarizing the change and linking to the issue.
- [x] Add `.. versionchanged::` entries in any relevant code docs.
- [x] Run `pre-commit` hooks and fix any issues.
- [x] Run `pytest` and `tox`, no tests failed.


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 24eabda..c6aa810 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -201,6 +201,8 @@ Unreleased
     applications to translate Click's built-in strings. :issue:`303`
 -   Writing invalid characters  to ``stderr`` when using the test runner
     does not raise a ``UnicodeEncodeError``. :issue:`848`
+-   Fix an issue where ``readline`` would clear the entire ``prompt()``
+    line instead of only the input when pressing backspace. :issue:`665`
 
 
 Version 7.1.2
diff --git a/src/click/termui.py b/src/click/termui.py
index 3a7e085..9850cf5 100644
--- a/src/click/termui.py
+++ b/src/click/termui.py
@@ -127,8 +127,10 @@ def prompt(
         try:
             # Write the prompt separately so that we get nice
             # coloring through colorama on Windows
-            echo(text, nl=False, err=err)
-            return f("")
+            echo(text.rstrip(" "), nl=False, err=err)
+            # Echo a space to stdout to work around an issue where
+            # readline causes backspace to clear the whole line.
+            return f(" ")
         except (KeyboardInterrupt, EOFError):
             # getpass doesn't print a newline if the user aborts input with ^C.
             # Allegedly this behavior is inherited from getpass(3).


Test patch:
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 3150b09..b3cfe70 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -154,10 +154,10 @@ def test_prompts_abort(monkeypatch, capsys):
     try:
         click.prompt("Password", hide_input=True)
     except click.Abort:
-        click.echo("Screw you.")
+        click.echo("interrupted")
 
     out, err = capsys.readouterr()
-    assert out == "Password: \nScrew you.\n"
+    assert out == "Password:\ninterrupted\n"
 
 
 def _test_gen_func():
@@ -255,8 +255,8 @@ def test_echo_writing_to_standard_error(capfd, monkeypatch):
     emulate_input("asdlkj\n")
     click.prompt("Prompt to stderr", err=True)
     out, err = capfd.readouterr()
-    assert out == ""
-    assert err == "Prompt to stderr: "
+    assert out == " "
+    assert err == "Prompt to stderr:"
 
     emulate_input("y\n")
     click.confirm("Prompt to stdin")