https://github.com/python/cpython/commit/83e5dc0f4d0d8d71288f162840b36f210fb03abf
commit: 83e5dc0f4d0d8d71288f162840b36f210fb03abf
branch: main
author: Dino Viehland <[email protected]>
committer: ambv <[email protected]>
date: 2024-09-27T00:10:36+02:00
summary:

gh-124628: Pyrepl inputs on Windows shouldn't always be blocking reads (#124629)

files:
M Lib/_pyrepl/windows_console.py

diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index f7a0095d795ac6..d457d2b5a338eb 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -371,15 +371,19 @@ def _getscrollbacksize(self) -> int:
 
         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 @@ def get_event(self, block: bool = True) -> Event | None:
             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 @@ def flushoutput(self) -> None:
 
     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 @@ class INPUT_RECORD(Structure):
     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 @@ def _win_only(*args, **kwargs):
     ScrollConsoleScreenBuffer = _win_only
     SetConsoleMode = _win_only
     ReadConsoleInput = _win_only
+    GetNumberOfConsoleInputEvents = _win_only
+    FlushConsoleInputBuffer = _win_only
     OutHandle = 0
     InHandle = 0

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to