summaryrefslogtreecommitdiffstats
path: root/Lib/_pyrepl
diff options
context:
space:
mode:
authorDino Viehland <dinoviehland@meta.com>2024-09-26 22:10:36 (GMT)
committerGitHub <noreply@github.com>2024-09-26 22:10:36 (GMT)
commit83e5dc0f4d0d8d71288f162840b36f210fb03abf (patch)
tree94dd3ddbc748a7ec61a0b08b7dc2af57479d5de6 /Lib/_pyrepl
parent66cc6d4c502074ddbfeda1be28fae6aa4535e4a8 (diff)
downloadcpython-83e5dc0f4d0d8d71288f162840b36f210fb03abf.zip
cpython-83e5dc0f4d0d8d71288f162840b36f210fb03abf.tar.gz
cpython-83e5dc0f4d0d8d71288f162840b36f210fb03abf.tar.bz2
gh-124628: Pyrepl inputs on Windows shouldn't always be blocking reads (#124629)
Diffstat (limited to 'Lib/_pyrepl')
-rw-r--r--Lib/_pyrepl/windows_console.py30
1 files changed, 21 insertions, 9 deletions
diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index f7a0095..d457d2b 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -371,15 +371,19 @@ class WindowsConsole(Console):
return info.srWindow.Bottom # type: ignore[no-any-return]
- def _read_input(self) -> INPUT_RECORD | None:
+ def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
+ if not block:
+ events = DWORD()
+ if not GetNumberOfConsoleInputEvents(InHandle, events):
+ raise WinError(GetLastError())
+ if not events.value:
+ return None
+
rec = INPUT_RECORD()
read = DWORD()
if not ReadConsoleInput(InHandle, rec, 1, read):
raise WinError(GetLastError())
- if read.value == 0:
- return None
-
return rec
def get_event(self, block: bool = True) -> Event | None:
@@ -390,10 +394,8 @@ class WindowsConsole(Console):
return self.event_queue.pop()
while True:
- rec = self._read_input()
+ rec = self._read_input(block)
if rec is None:
- if block:
- continue
return None
if rec.EventType == WINDOW_BUFFER_SIZE_EVENT:
@@ -464,8 +466,8 @@ class WindowsConsole(Console):
def forgetinput(self) -> None:
"""Forget all pending, but not yet processed input."""
- while self._read_input() is not None:
- pass
+ if not FlushConsoleInputBuffer(InHandle):
+ raise WinError(GetLastError())
def getpending(self) -> Event:
"""Return the characters that have been typed but not yet
@@ -590,6 +592,14 @@ if sys.platform == "win32":
ReadConsoleInput.argtypes = [HANDLE, POINTER(INPUT_RECORD), DWORD, POINTER(DWORD)]
ReadConsoleInput.restype = BOOL
+ GetNumberOfConsoleInputEvents = _KERNEL32.GetNumberOfConsoleInputEvents
+ GetNumberOfConsoleInputEvents.argtypes = [HANDLE, POINTER(DWORD)]
+ GetNumberOfConsoleInputEvents.restype = BOOL
+
+ FlushConsoleInputBuffer = _KERNEL32.FlushConsoleInputBuffer
+ FlushConsoleInputBuffer.argtypes = [HANDLE]
+ FlushConsoleInputBuffer.restype = BOOL
+
OutHandle = GetStdHandle(STD_OUTPUT_HANDLE)
InHandle = GetStdHandle(STD_INPUT_HANDLE)
else:
@@ -602,5 +612,7 @@ else:
ScrollConsoleScreenBuffer = _win_only
SetConsoleMode = _win_only
ReadConsoleInput = _win_only
+ GetNumberOfConsoleInputEvents = _win_only
+ FlushConsoleInputBuffer = _win_only
OutHandle = 0
InHandle = 0