mirror of
https://github.com/python/cpython.git
synced 2025-09-25 01:43:11 +00:00
GH-130328: pasting in new REPL is slow on Windows (GH-132884)
This commit is contained in:
parent
ae37f3d3c0
commit
acb222ce8f
2 changed files with 28 additions and 21 deletions
|
@ -22,8 +22,6 @@ from __future__ import annotations
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
|
||||||
import msvcrt
|
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes.wintypes import (
|
from ctypes.wintypes import (
|
||||||
|
@ -44,7 +42,7 @@ from .utils import wlen
|
||||||
from .windows_eventqueue import EventQueue
|
from .windows_eventqueue import EventQueue
|
||||||
|
|
||||||
try:
|
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:
|
except:
|
||||||
# Keep MyPy happy off Windows
|
# Keep MyPy happy off Windows
|
||||||
from ctypes import CDLL as WinDLL, cdll as windll
|
from ctypes import CDLL as WinDLL, cdll as windll
|
||||||
|
@ -52,6 +50,9 @@ except:
|
||||||
def GetLastError() -> int:
|
def GetLastError() -> int:
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
def get_last_error() -> int:
|
||||||
|
return 42
|
||||||
|
|
||||||
class WinError(OSError): # type: ignore[no-redef]
|
class WinError(OSError): # type: ignore[no-redef]
|
||||||
def __init__(self, err: int | None, descr: str | None = None) -> None:
|
def __init__(self, err: int | None, descr: str | None = None) -> None:
|
||||||
self.err = err
|
self.err = err
|
||||||
|
@ -108,6 +109,12 @@ CLEAR = "\x1b[H\x1b[J"
|
||||||
ALT_ACTIVE = 0x01 | 0x02
|
ALT_ACTIVE = 0x01 | 0x02
|
||||||
CTRL_ACTIVE = 0x04 | 0x08
|
CTRL_ACTIVE = 0x04 | 0x08
|
||||||
|
|
||||||
|
WAIT_TIMEOUT = 0x102
|
||||||
|
WAIT_FAILED = 0xFFFFFFFF
|
||||||
|
|
||||||
|
# from winbase.h
|
||||||
|
INFINITE = 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
class _error(Exception):
|
class _error(Exception):
|
||||||
pass
|
pass
|
||||||
|
@ -409,12 +416,8 @@ class WindowsConsole(Console):
|
||||||
return info.srWindow.Bottom # type: ignore[no-any-return]
|
return info.srWindow.Bottom # type: ignore[no-any-return]
|
||||||
|
|
||||||
def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
|
def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
|
||||||
if not block:
|
if not block and not self.wait(timeout=0):
|
||||||
events = DWORD()
|
return None
|
||||||
if not GetNumberOfConsoleInputEvents(InHandle, events):
|
|
||||||
raise WinError(GetLastError())
|
|
||||||
if not events.value:
|
|
||||||
return None
|
|
||||||
|
|
||||||
rec = INPUT_RECORD()
|
rec = INPUT_RECORD()
|
||||||
read = DWORD()
|
read = DWORD()
|
||||||
|
@ -522,14 +525,16 @@ class WindowsConsole(Console):
|
||||||
|
|
||||||
def wait(self, timeout: float | None) -> bool:
|
def wait(self, timeout: float | None) -> bool:
|
||||||
"""Wait for an event."""
|
"""Wait for an event."""
|
||||||
# Poor man's Windows select loop
|
if timeout is None:
|
||||||
start_time = time.time()
|
timeout = INFINITE
|
||||||
while True:
|
else:
|
||||||
if msvcrt.kbhit(): # type: ignore[attr-defined]
|
timeout = int(timeout)
|
||||||
return True
|
ret = WaitForSingleObject(InHandle, timeout)
|
||||||
if timeout and time.time() - start_time > timeout / 1000:
|
if ret == WAIT_FAILED:
|
||||||
return False
|
raise WinError(get_last_error())
|
||||||
time.sleep(0.01)
|
elif ret == WAIT_TIMEOUT:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def repaint(self) -> None:
|
def repaint(self) -> None:
|
||||||
raise NotImplementedError("No repaint support")
|
raise NotImplementedError("No repaint support")
|
||||||
|
@ -649,14 +654,15 @@ if sys.platform == "win32":
|
||||||
ReadConsoleInput.argtypes = [HANDLE, POINTER(INPUT_RECORD), DWORD, POINTER(DWORD)]
|
ReadConsoleInput.argtypes = [HANDLE, POINTER(INPUT_RECORD), DWORD, POINTER(DWORD)]
|
||||||
ReadConsoleInput.restype = BOOL
|
ReadConsoleInput.restype = BOOL
|
||||||
|
|
||||||
GetNumberOfConsoleInputEvents = _KERNEL32.GetNumberOfConsoleInputEvents
|
|
||||||
GetNumberOfConsoleInputEvents.argtypes = [HANDLE, POINTER(DWORD)]
|
|
||||||
GetNumberOfConsoleInputEvents.restype = BOOL
|
|
||||||
|
|
||||||
FlushConsoleInputBuffer = _KERNEL32.FlushConsoleInputBuffer
|
FlushConsoleInputBuffer = _KERNEL32.FlushConsoleInputBuffer
|
||||||
FlushConsoleInputBuffer.argtypes = [HANDLE]
|
FlushConsoleInputBuffer.argtypes = [HANDLE]
|
||||||
FlushConsoleInputBuffer.restype = BOOL
|
FlushConsoleInputBuffer.restype = BOOL
|
||||||
|
|
||||||
|
WaitForSingleObject = _KERNEL32.WaitForSingleObject
|
||||||
|
WaitForSingleObject.argtypes = [HANDLE, DWORD]
|
||||||
|
WaitForSingleObject.restype = DWORD
|
||||||
|
|
||||||
OutHandle = GetStdHandle(STD_OUTPUT_HANDLE)
|
OutHandle = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
InHandle = GetStdHandle(STD_INPUT_HANDLE)
|
InHandle = GetStdHandle(STD_INPUT_HANDLE)
|
||||||
else:
|
else:
|
||||||
|
@ -670,7 +676,7 @@ else:
|
||||||
GetConsoleMode = _win_only
|
GetConsoleMode = _win_only
|
||||||
SetConsoleMode = _win_only
|
SetConsoleMode = _win_only
|
||||||
ReadConsoleInput = _win_only
|
ReadConsoleInput = _win_only
|
||||||
GetNumberOfConsoleInputEvents = _win_only
|
|
||||||
FlushConsoleInputBuffer = _win_only
|
FlushConsoleInputBuffer = _win_only
|
||||||
|
WaitForSingleObject = _win_only
|
||||||
OutHandle = 0
|
OutHandle = 0
|
||||||
InHandle = 0
|
InHandle = 0
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Speedup pasting in ``PyREPL`` on Windows. Fix by Chris Eibl.
|
Loading…
Add table
Add a link
Reference in a new issue