aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/_pyrepl/windows_console.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/_pyrepl/windows_console.py')
-rw-r--r--Lib/_pyrepl/windows_console.py44
1 files changed, 26 insertions, 18 deletions
diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index a294d627b0e..c56dcd6d7dd 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -24,6 +24,7 @@ import os
import sys
import ctypes
+import types
from ctypes.wintypes import (
_COORD,
WORD,
@@ -58,6 +59,12 @@ except:
self.err = err
self.descr = descr
+# declare nt optional to allow None assignment on other platforms
+nt: types.ModuleType | None
+try:
+ import nt
+except ImportError:
+ nt = None
TYPE_CHECKING = False
@@ -121,9 +128,8 @@ class _error(Exception):
def _supports_vt():
try:
- import nt
return nt._supports_virtual_terminal()
- except (ImportError, AttributeError):
+ except AttributeError:
return False
class WindowsConsole(Console):
@@ -235,11 +241,9 @@ class WindowsConsole(Console):
@property
def input_hook(self):
- try:
- import nt
- except ImportError:
- return None
- if nt._is_inputhook_installed():
+ # avoid inline imports here so the repl doesn't get flooded
+ # with import logging from -X importtime=2
+ if nt is not None and nt._is_inputhook_installed():
return nt._inputhook
def __write_changed_line(
@@ -415,10 +419,7 @@ class WindowsConsole(Console):
return info.srWindow.Bottom # type: ignore[no-any-return]
- def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
- if not block and not self.wait(timeout=0):
- return None
-
+ def _read_input(self) -> INPUT_RECORD | None:
rec = INPUT_RECORD()
read = DWORD()
if not ReadConsoleInput(InHandle, rec, 1, read):
@@ -427,14 +428,10 @@ class WindowsConsole(Console):
return rec
def _read_input_bulk(
- self, block: bool, n: int
+ self, n: int
) -> tuple[ctypes.Array[INPUT_RECORD], int]:
rec = (n * INPUT_RECORD)()
read = DWORD()
-
- if not block and not self.wait(timeout=0):
- return rec, 0
-
if not ReadConsoleInput(InHandle, rec, n, read):
raise WinError(GetLastError())
@@ -445,8 +442,11 @@ class WindowsConsole(Console):
and there is no event pending, otherwise waits for the
completion of an event."""
+ if not block and not self.wait(timeout=0):
+ return None
+
while self.event_queue.empty():
- rec = self._read_input(block)
+ rec = self._read_input()
if rec is None:
return None
@@ -547,12 +547,20 @@ class WindowsConsole(Console):
if e2:
e.data += e2.data
- recs, rec_count = self._read_input_bulk(False, 1024)
+ recs, rec_count = self._read_input_bulk(1024)
for i in range(rec_count):
rec = recs[i]
+ # In case of a legacy console, we do not only receive a keydown
+ # event, but also a keyup event - and for uppercase letters
+ # an additional SHIFT_PRESSED event.
if rec and rec.EventType == KEY_EVENT:
key_event = rec.Event.KeyEvent
+ if not key_event.bKeyDown:
+ continue
ch = key_event.uChar.UnicodeChar
+ if ch == "\x00":
+ # ignore SHIFT_PRESSED and special keys
+ continue
if ch == "\r":
ch += "\n"
e.data += ch