diff options
author | Seb Aebischer <8686939+saebischer@users.noreply.github.com> | 2021-03-06 16:47:26 +0000 |
---|---|---|
committer | David Lord <davidism@gmail.com> | 2021-04-13 13:28:09 -0700 |
commit | 0d01686fe6be5c335f50098a06b7e847a2753452 (patch) | |
tree | 9661fa2ef947b581b87844cb2e2a37e246b09f7c /src/click/testing.py | |
parent | 0dc6d74df5c984ff923f5d17e97bf94a21b3a3cd (diff) | |
download | click-0d01686fe6be5c335f50098a06b7e847a2753452.tar.gz |
fix output when using echo_stdin
echo calls to read1
pause echo when using hidden input prompt and getchar
don't buffer reads to avoid echoing early
Diffstat (limited to 'src/click/testing.py')
-rw-r--r-- | src/click/testing.py | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/click/testing.py b/src/click/testing.py index 3bbdbff..89e58da 100644 --- a/src/click/testing.py +++ b/src/click/testing.py @@ -16,17 +16,22 @@ class EchoingStdin: def __init__(self, input, output): self._input = input self._output = output + self.paused = False def __getattr__(self, x): return getattr(self._input, x) def _echo(self, rv): - self._output.write(rv) + if not self.paused: + self._output.write(rv) return rv def read(self, n=-1): return self._echo(self._input.read(n)) + def read1(self, n=-1): + return self._echo(self._input.read1(n)) + def readline(self, n=-1): return self._echo(self._input.readline(n)) @@ -204,10 +209,16 @@ class CliRunner: if self.echo_stdin: input = EchoingStdin(input, bytes_output) + echo_input = input sys.stdin = input = _NamedTextIOWrapper( input, encoding=self.charset, name="<stdin>", mode="r" ) + if self.echo_stdin: + # Force unbuffered reads, otherwise the underlying EchoingStdin + # stream will echo a big chunk of input on the first read. + input._CHUNK_SIZE = 1 + sys.stdout = _NamedTextIOWrapper( bytes_output, encoding=self.charset, name="<stdout>", mode="w" ) @@ -228,20 +239,30 @@ class CliRunner: def visible_input(prompt=None): sys.stdout.write(prompt or "") val = input.readline().rstrip("\r\n") - sys.stdout.write(f"{val}\n") + if not self.echo_stdin: + sys.stdout.write(f"{val}\n") sys.stdout.flush() return val def hidden_input(prompt=None): sys.stdout.write(f"{prompt or ''}\n") sys.stdout.flush() - return input.readline().rstrip("\r\n") + if self.echo_stdin: + echo_input.paused = True + val = input.readline().rstrip("\r\n") + if self.echo_stdin: + echo_input.paused = False + return val def _getchar(echo): + if not echo and self.echo_stdin: + echo_input.paused = True char = sys.stdin.read(1) - if echo: + if echo and not self.echo_stdin: sys.stdout.write(char) sys.stdout.flush() + elif not echo and self.echo_stdin: + echo_input.paused = False return char default_color = color |