prompt-toolkit / prompt-toolkit/python-prompt-toolkit

in-depth patch_stdout() primer/documentation?

Open
#1,866 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
10.6k
Forks
815
PR merge metrics
No merged PRs in 30d

Description

I've built full-screen apps where of course I would have no need for patch_stdout(). More recently I started enriching "regular" scripts with occasional progress bars and prompts. For what I need a full screen app seemed kind of overkill, and I liked the idea for the experience to be easily able to gracefully degrade when the output is being piped into log files.

I wish the documentation around patch_stdout() would go a lot more in depth and perhaps enumerate all widgets that would and would not "bypass" the patched standard output, together with good and bad patterns. From certain examples, it seems like its context is only wrapping the use of certain widgets while other threads print to the terminal. Yet, I've run into situations where if I don't wrap a print in a patch_stdout() context, the print ruins the terminal output for a progress bar widget from a different coroutine than the one the print is coming from.

So, I've been lazily sprinkling with patch_stdout() all over the place, without thinking too much. I'd use it generously and a bit too naively, without trying to understand things too well and perhaps counting too much on the fact that its implementation looked like it should be re-entrant. Of course I ended up with a little bit of a nightmare at hand.

Maybe I should just be less stubborn and build yet another full-screen app instead.

In any case, here's some of the nightmarish stuff I have been able to cause thus far:

  • ValueError: write to closed file
  • ValueError('I/O operation on closed file.')
  • RuntimeError('File descriptor 0 is used by transport <ReadUnixTransport closed=False reading=True 0x7fc771440380>')
  • RuntimeError: File descriptor 0 is used by transport <ReadUnixTransport closed=False reading=True 0x7fd0b404c380>
Error in sys.excepthook:
object address  : 0x7fc7626ef760
object refcount : 1
object type     : 0x7fc776a2f640
object type name: ValueError
object repr     : ValueError('I/O operation on closed file.')
lost sys.stderr

Original exception was:
object address  : 0x7fc7627eba60
object refcount : 5
object type     : 0x7fc776a30da0
object type name: RuntimeError
object repr     : RuntimeError('File descriptor 0 is used by transport <ReadUnixTransport closed=False reading=True 0x7fc771440380>')
lost sys.stderr
  File "setup.py", line 2173, in setup
    confirmation = await session.prompt_async()
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/shortcuts/prompt.py", line 1220, in prompt_async
    return await self.app.run_async(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/application/application.py", line 886, in run_async
    return await _run_async(f)
           ^^^^^^^^^^^^^^^^^^^
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/application/application.py", line 734, in _run_async
    with self.input.raw_mode(), self.input.attach(
  File "/usr/lib/python3.12/contextlib.py", line 137, in __enter__
    return next(self.gen)
           ^^^^^^^^^^^^^^
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/input/vt100.py", line 165, in _attached_input
    loop.add_reader(fd, callback_wrapper)
  File "uvloop/loop.pyx", line 2441, in uvloop.loop.Loop.add_reader
  File "uvloop/loop.pyx", line 772, in uvloop.loop.Loop._add_reader
  File "uvloop/loop.pyx", line 762, in uvloop.loop.Loop._ensure_fd_no_transport
RuntimeError: File descriptor 0 is used by transport <ReadUnixTransport closed=False reading=True 0x7fd0b404c380>
NoneType: None
  File "/usr/lib/python3.12/contextlib.py", line 137, in __enter__
    return next(self.gen)
           ^^^^^^^^^^^^^^
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/input/vt100.py", line 165, in _attached_input
    loop.add_reader(fd, callback_wrapper)
  File "uvloop/loop.pyx", line 2441, in uvloop.loop.Loop.add_reader
  File "uvloop/loop.pyx", line 772, in uvloop.loop.Loop._add_reader
  File "uvloop/loop.pyx", line 762, in uvloop.loop.Loop._ensure_fd_no_transport
RuntimeError: File descriptor 0 is used by transport <ReadUnixTransport closed=False reading=True 0x7fd0b404c380>
NoneType: None
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/shortcuts/utils.py", line 139, in render
    renderer_print_formatted_text(
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/renderer.py", line 813, in print_formatted_text
    output.flush()
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/output/vt100.py", line 693, in flush
    flush_stdout(self.stdout, data)
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/output/flush_stdout.py", line 33, in flush_stdout
    stdout.buffer.write(data.encode(stdout.encoding or "utf-8", "replace"))
ValueError: write to closed file
NoneType: None
  File "setup.py", line 2475, in <module>
    print()
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/shortcuts/utils.py", line 164, in print_formatted_text
    render()
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/shortcuts/utils.py", line 139, in render
    renderer_print_formatted_text(
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/renderer.py", line 813, in print_formatted_text
    output.flush()
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/output/vt100.py", line 693, in flush
    flush_stdout(self.stdout, data)
  File "venv312/lib/python3.12/site-packages/prompt_toolkit/output/flush_stdout.py", line 33, in flush_stdout
    stdout.buffer.write(data.encode(stdout.encoding or "utf-8", "replace"))
ValueError: write to closed file
NoneType: None

I understand that providing a minimal code snippet to reproduce these issues would be better, and perhaps I'll find the time to do so in the future. Meanwhile, is there any chance from the little info I could provide you'd have any hint as to how I should be doing instead and what I shouldn't be doing?

Thank you!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names patch_stdout(), prompt_async(), and traceback paths in prompt_toolkit/input/vt100.py, output/vt100.py, and output/flush_stdout.py. Start by reading the existing patch_stdout() documentation and tracing those entry points; done means documenting widget interactions, safe and unsafe usage patterns, and guidance for reproducing the reported failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.