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

Catching exception from key bindings handler

Open
#1,851 1 comment 1 reaction 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

Is it possible to catch an exception raised in a key bindings handler? Not inside the application, but it should be possible outside the application. Consider the following MVE:

import asyncio

from prompt_toolkit import PromptSession
from prompt_toolkit.key_binding import KeyBindings


async def main():
    bindings = KeyBindings()

    @bindings.add("c-t")
    def handler(_):
        raise Exception("Hello!")

    try:
        await PromptSession().prompt_async("> ", key_bindings=bindings)
    except Exception as ex:
        print(f"Caught exception: {ex}")


if __name__ == "__main__":
    asyncio.run(main())

Running that program and hitting CTRL+T at the prompt should raise an exception in the handler function, and since keyboard processing happen inside the prompt_async application the exception should be propagated to the caller of prompt_async(), I think.

But I get the following error:

Unhandled exception in event loop:                                                                                                                          
  File "/usr/lib/python3.11/asyncio/events.py", line 80, in _run                                                                                            
    self._context.run(self._callback, *self._args)                                                                                                          
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/input/vt100.py", line 162, in callback_wrapper                                                     
    callback()                                                                                                                                              
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/application/application.py", line 714, in read_from_input_in_context                               
    context.copy().run(read_from_input)                                                                                                                     
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/application/application.py", line 694, in read_from_input                                          
    self.key_processor.process_keys()                                                                                                                       
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_processor.py", line 272, in process_keys                                           
    self._process_coroutine.send(key_press)                                                                                                                 
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_processor.py", line 187, in _process                                               
    self._call_handler(matches[-1], key_sequence=buffer[:])                                                                                                 
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_processor.py", line 322, in _call_handler                                          
    handler.call(event)                                                                                                                                     
  File "/usr/lib/python3.11/site-packages/prompt_toolkit/key_binding/key_bindings.py", line 126, in call                                                    
    result = self.handler(event)                                                                                                                            
             ^^^^^^^^^^^^^^^^^^^                                                                                                                            
  File "$HOME/ptktest.py", line 12, in handler                                                                                                         
    raise Exception("Hello!")                                                                                                                               
                                                                                                                                                            
Exception Hello!                                                                                                                                            
Press ENTER to continue...                                                                                                                                  

I expect it to just print:

Caught exception: Hello!

And then exit.

Is this possible in any way?

Best regards,
Tage

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

Run the provided asyncio MVE with the Ctrl+T key binding, then trace exception handling through prompt_async, application.py, key_processor.py, and input/vt100.py using the displayed stack trace. Done means the handler exception reaches the caller so the program prints “Caught exception: Hello!” and exits instead of showing the event-loop error screen.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.