Skip to content

Commit a64f4c4

Browse files
committed
read in chunks
1 parent 4098e3d commit a64f4c4

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

Lib/_pyrepl/windows_console.py

+37-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ def __init__(self, err: int | None, descr: str | None = None) -> None:
6464
if TYPE_CHECKING:
6565
from typing import IO
6666

67+
INPUT_BUFFER_LEN = 10 * 1024
68+
6769
# Virtual-Key Codes: https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
6870
VK_MAP: dict[int, str] = {
6971
0x23: "end", # VK_END
@@ -165,6 +167,10 @@ def __init__(
165167
# Console I/O is redirected, fallback...
166168
self.out = None
167169

170+
self.input_buffer = (INPUT_RECORD * INPUT_BUFFER_LEN)()
171+
self.input_buffer_pos = 0
172+
self.input_buffer_count = 0
173+
168174
def refresh(self, screen: list[str], c_xy: tuple[int, int]) -> None:
169175
"""
170176
Refresh the console screen.
@@ -415,16 +421,27 @@ def _getscrollbacksize(self) -> int:
415421

416422
return info.srWindow.Bottom # type: ignore[no-any-return]
417423

424+
def more_in_buffer(self) -> bool:
425+
return self.input_buffer_pos < self.input_buffer_count - 1
426+
418427
def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
419428
if not block and not self.wait(timeout=0):
420429
return None
421430

422-
rec = INPUT_RECORD()
431+
if self.more_in_buffer():
432+
self.input_buffer_pos += 1
433+
return self.input_buffer[self.input_buffer_pos]
434+
435+
# read next chunk
436+
self.input_buffer_pos = 0
437+
self.input_buffer_count = 0
423438
read = DWORD()
424-
if not ReadConsoleInput(InHandle, rec, 1, read):
439+
440+
if not ReadConsoleInput(InHandle, self.input_buffer, INPUT_BUFFER_LEN, read):
425441
raise WinError(GetLastError())
426442

427-
return rec
443+
self.input_buffer_count = read.value
444+
return self.input_buffer[0]
428445

429446
def get_event(self, block: bool = True) -> Event | None:
430447
"""Return an Event instance. Returns None if |block| is false
@@ -521,9 +538,14 @@ def forgetinput(self) -> None:
521538
def getpending(self) -> Event:
522539
"""Return the characters that have been typed but not yet
523540
processed."""
524-
return Event("key", "", b"")
541+
e = Event("key", "", b"")
542+
543+
while not self.event_queue.empty():
544+
e2 = self.event_queue.get()
545+
e.data += e2.data
546+
e.raw += e.raw
525547

526-
def wait(self, timeout: float | None) -> bool:
548+
def wait_for_event(self, timeout: float | None) -> bool:
527549
"""Wait for an event."""
528550
if timeout is None:
529551
timeout = INFINITE
@@ -536,6 +558,16 @@ def wait(self, timeout: float | None) -> bool:
536558
return False
537559
return True
538560

561+
def wait(self, timeout: float | None = None) -> bool:
562+
"""
563+
Wait for events on the console.
564+
"""
565+
return (
566+
not self.event_queue.empty()
567+
or self.more_in_buffer()
568+
or self.wait_for_event(timeout)
569+
)
570+
539571
def repaint(self) -> None:
540572
raise NotImplementedError("No repaint support")
541573

0 commit comments

Comments
 (0)