Fixing an ipython Windows ConEmu only bug on 'MouseEventType.MOUSE_DOWN'#
This post is for manually fixing an ipython Windows ConEmu only bug (from prompt_toolkit): Exception ''MouseEventType.MOUSE_DOWN'' is not a valid MouseEventType.
Problem#
Previously I updated the python version, the ipython version and maybe ConEmu on my Windows 10 (I don't remember which one exactly), I got an error when I wanted to copy some text from ipython repl in ConEmu console by the right mouse click:
ps.7.0.0 | py.3.8.2❯ ipython
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.
Unhandled exception in event loop:
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\asyncio\events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\input\win32.py", line 512, in ready
callback()
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\application\application.py", line 653, in read_from_input
self.key_processor.process_keys()
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\key_binding\key_processor.py", line 274, in process_keys
self._process_coroutine.send(key_press)
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\key_binding\key_processor.py", line 186, in _process
self._call_handler(matches[-1], key_sequence=buffer[:])
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\key_binding\key_processor.py", line 329, in _call_handler
handler.call(event)
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\key_binding\key_bindings.py", line 101, in call
self.handler(event)
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\key_binding\bindings\mouse.py", line 128, in _mouse
event_type = MouseEventType(pieces[0])
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\enum.py", line 304, in __call__
return cls.__new__(cls, value)
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\enum.py", line 595, in __new__
raise exc
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\enum.py", line 579, in __new__
result = cls._missing_(value)
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\enum.py", line 608, in _missing_
raise ValueError("%r is not a valid %s" % (value, cls.__name__))
Exception 'MouseEventType.MOUSE_DOWN' is not a valid MouseEventType
Press ENTER to continue...
Root cause#
From the error stack, we can identify that it should be this line from the prompt_toolkit which throws the error:
File "d:\xiang\tools\scoop\apps\python\3.8.2\lib\site-packages\prompt_toolkit\key_binding\bindings\mouse.py", line 128, in _mouse
event_type = MouseEventType(pieces[0])
And hereunder is the ipython and prompt_toolkit version installed on my Windows 10.
ps.7.0.0 | py.3.8.2❯ pip list | sls ipython, prompt
ipython 7.13.0
ipython-genutils 0.2.0
prompt-toolkit 3.0.4
Let's check the source code of the prompt_toolkit:
@key_bindings.add(Keys.WindowsMouseEvent)
def _mouse(event: E) -> None:
"""
Handling of mouse events for Windows.
"""
assert is_windows() # This key binding should only exist for Windows.
# Parse data.
pieces = event.data.split(";")
event_type = MouseEventType(pieces[0])
And let's add some simple debug code by using print():
@key_bindings.add(Keys.WindowsMouseEvent)
def _mouse(event: E) -> None:
"""
Handling of mouse events for Windows.
"""
assert is_windows() # This key binding should only exist for Windows.
# Parse data.
pieces = event.data.split(";")
# start debug
for met in MouseEventType:
print("met:", met)
print("pieces[0]:", pieces[0])
# end debug
event_type = MouseEventType(pieces[0])
Reproduce the error in ipython, I got the print info:
met: MouseEventType.MOUSE_UP
met: MouseEventType.MOUSE_DOWN
met: MouseEventType.SCROLL_UP
met: MouseEventType.SCROLL_DOWN
pieces[0]: MouseEventType.MOUSE_DOWN
Visually it seems that pieces[0]
is in the MouseEventType, but as MouseEventType is an Enum type, the correct syntax is that pieces[0]
should not be prefixed by the enum class name MouseEventType
, instead we can use the string format of the type, so called programmatic access: MouseEventType["MOUSE_DOWN"]
Solution#
Adding a split on pieces[0]
object can workaround the issue, but to fix it definitively, in fact, the author already fixed it a couple of weeks ago:
https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1099
https:/ /pull/1105/commits/d2e7da3be5e46a5c8b432f67f78b662541b957de
# prompt_toolkit/input/win32.py
# On a key press, generate both the mouse down and up event.
for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]:
data = ";".join(
- [str(event_type), str(ev.MousePosition.X), str(ev.MousePosition.Y)]
+ [event_type.value, str(ev.MousePosition.X), str(ev.MousePosition.Y)]
)
result.append(KeyPress(Keys.WindowsMouseEvent, data))