rich icon indicating copy to clipboard operation
rich copied to clipboard

[BUG] console.input always prints to stdout regardless of stderr setting

Open AdmiralNemo opened this issue 3 years ago • 4 comments

Describe the bug

I have an application that is intended be run as part of a pipeline, e.g. myapp | sendmail, but is very interactive, with menus, text inputs, etc. I want to use Rich to make it nicer, but I am stuck getting console.input to work without printing anything to stdout.

from rich.console import Console

console = Console(stderr=True)
console.print('Hello world')
console.input('Input: ')
$ myapp > /dev/null
Hello world

(hangs here waiting for input, but prompt is hidden)

The problem seems to be that Console.input() just calls the built-in input() function, which is known to behave incorrectly (bpo #1927). Without Rich, it's simple enough to work around that behavior by printing the prompt directly to sys.stderr and passing an empty string to input(). Indeed, I could do the same with Rich and avoid using Console.input(), but this means I cannot use things like Prompt.ask, etc.

Console.input() does have a couple of code paths where it respects self.file. I thought calling console.input(..., stream=sys.stdin) might work, but it does not because Console.input does not call self.file.flush() after printing the prompt.

I think at the very least, Console.input() should call self.file.flush() after writing the prompt. I don't think this would hurt anything, and it would allow Rich to keep its current behavior of just calling input() in the default case. If people want to avoid printing anything to stdout, they can work around the behavior by passing stream=sys.stdin. On the other hand, I am not sure what advantage using input() provides, so it may be a better idea to remove that code path and make the default behavior be to print the prompt directly and then read a line from stdin.

AdmiralNemo avatar Dec 14 '21 22:12 AdmiralNemo

@AdmiralNemo I am unable to reproduce the issue on my side, is the issue fixed?

spotted-cat avatar Jan 27 '22 15:01 spotted-cat

@spotted-cat no, the issue is not fixed. The code listed in the original description still behaves exactly the same on rich-11.0.0. The prompt text from console.input is always written to standard output.

AdmiralNemo avatar Jan 28 '22 13:01 AdmiralNemo

@AdmiralNemo currently the code for Console.input() passes the prompt argument to Console.print() which is captured to give the resulting raw string, This raw string eventually is passed as the prompt argument to the inbuilt input function. One way to rectify your problem would be to check for the stderr flag and if it is set then to directly print the text using Console.print() and avoid passing any promp arguments to the inbuilt input() function? Are there any problems with this approach ??

spotted-cat avatar Jan 31 '22 08:01 spotted-cat

Indeed, I could do the same with Rich and avoid using Console.input(), but this means I cannot use things like Prompt.ask, etc.

AdmiralNemo avatar Jan 31 '22 14:01 AdmiralNemo

I hope we solved your problem.

If you like using Rich, you might also enjoy Textual

github-actions[bot] avatar Dec 24 '22 10:12 github-actions[bot]