aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib
diff options
context:
space:
mode:
authorChris Eibl <138194463+chris-eibl@users.noreply.github.com>2025-04-29 18:03:45 +0200
committerGitHub <noreply@github.com>2025-04-29 18:03:45 +0200
commitacb222ce8ff1962b09112accabbcc4ed3d61cf6e (patch)
tree86d3a5231ce8a51cc616017d5f71f1e956d7f6ba /Lib
parentae37f3d3c0cc41a68174efd1a665f7baa0804801 (diff)
downloadcpython-acb222ce8ff1962b09112accabbcc4ed3d61cf6e.tar.gz
cpython-acb222ce8ff1962b09112accabbcc4ed3d61cf6e.zip
GH-130328: pasting in new REPL is slow on Windows (GH-132884)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/_pyrepl/windows_console.py48
1 files changed, 27 insertions, 21 deletions
diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index 47fd3fd8f89..17942c8df07 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -22,8 +22,6 @@ from __future__ import annotations
import io
import os
import sys
-import time
-import msvcrt
import ctypes
from ctypes.wintypes import (
@@ -44,7 +42,7 @@ from .utils import wlen
from .windows_eventqueue import EventQueue
try:
- from ctypes import GetLastError, WinDLL, windll, WinError # type: ignore[attr-defined]
+ from ctypes import get_last_error, GetLastError, WinDLL, windll, WinError # type: ignore[attr-defined]
except:
# Keep MyPy happy off Windows
from ctypes import CDLL as WinDLL, cdll as windll
@@ -52,6 +50,9 @@ except:
def GetLastError() -> int:
return 42
+ def get_last_error() -> int:
+ return 42
+
class WinError(OSError): # type: ignore[no-redef]
def __init__(self, err: int | None, descr: str | None = None) -> None:
self.err = err
@@ -108,6 +109,12 @@ CLEAR = "\x1b[H\x1b[J"
ALT_ACTIVE = 0x01 | 0x02
CTRL_ACTIVE = 0x04 | 0x08
+WAIT_TIMEOUT = 0x102
+WAIT_FAILED = 0xFFFFFFFF
+
+# from winbase.h
+INFINITE = 0xFFFFFFFF
+
class _error(Exception):
pass
@@ -409,12 +416,8 @@ 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:
- events = DWORD()
- if not GetNumberOfConsoleInputEvents(InHandle, events):
- raise WinError(GetLastError())
- if not events.value:
- return None
+ if not block and not self.wait(timeout=0):
+ return None
rec = INPUT_RECORD()
read = DWORD()
@@ -522,14 +525,16 @@ class WindowsConsole(Console):
def wait(self, timeout: float | None) -> bool:
"""Wait for an event."""
- # Poor man's Windows select loop
- start_time = time.time()
- while True:
- if msvcrt.kbhit(): # type: ignore[attr-defined]
- return True
- if timeout and time.time() - start_time > timeout / 1000:
- return False
- time.sleep(0.01)
+ if timeout is None:
+ timeout = INFINITE
+ else:
+ timeout = int(timeout)
+ ret = WaitForSingleObject(InHandle, timeout)
+ if ret == WAIT_FAILED:
+ raise WinError(get_last_error())
+ elif ret == WAIT_TIMEOUT:
+ return False
+ return True
def repaint(self) -> None:
raise NotImplementedError("No repaint support")
@@ -649,14 +654,15 @@ 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
+ WaitForSingleObject = _KERNEL32.WaitForSingleObject
+ WaitForSingleObject.argtypes = [HANDLE, DWORD]
+ WaitForSingleObject.restype = DWORD
+
OutHandle = GetStdHandle(STD_OUTPUT_HANDLE)
InHandle = GetStdHandle(STD_INPUT_HANDLE)
else:
@@ -670,7 +676,7 @@ else:
GetConsoleMode = _win_only
SetConsoleMode = _win_only
ReadConsoleInput = _win_only
- GetNumberOfConsoleInputEvents = _win_only
FlushConsoleInputBuffer = _win_only
+ WaitForSingleObject = _win_only
OutHandle = 0
InHandle = 0