Skip to content

Commit 93aee56

Browse files
[3.14] GH-130328: Speedup pasting in legacy console on Windows (gh-133728) (#134653)
(cherry picked from commit 91b4886) Co-authored-by: Chris Eibl <[email protected]>
1 parent 80d70de commit 93aee56

File tree

5 files changed

+26
-12
lines changed

5 files changed

+26
-12
lines changed

Lib/_pyrepl/commands.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,13 @@ def do(self) -> None:
370370
r = self.reader
371371
text = self.event * r.get_arg()
372372
r.insert(text)
373+
if r.paste_mode:
374+
data = ""
375+
ev = r.console.getpending()
376+
data += ev.data
377+
if data:
378+
r.insert(data)
379+
r.last_refresh_cache.invalidated = True
373380

374381

375382
class insert_nl(EditCommand):
@@ -484,7 +491,6 @@ def do(self) -> None:
484491
data = ""
485492
start = time.time()
486493
while done not in data:
487-
self.reader.console.wait(100)
488494
ev = self.reader.console.getpending()
489495
data += ev.data
490496
trace(

Lib/_pyrepl/windows_console.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,7 @@ def _getscrollbacksize(self) -> int:
419419

420420
return info.srWindow.Bottom # type: ignore[no-any-return]
421421

422-
def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
423-
if not block and not self.wait(timeout=0):
424-
return None
425-
422+
def _read_input(self) -> INPUT_RECORD | None:
426423
rec = INPUT_RECORD()
427424
read = DWORD()
428425
if not ReadConsoleInput(InHandle, rec, 1, read):
@@ -431,14 +428,10 @@ def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
431428
return rec
432429

433430
def _read_input_bulk(
434-
self, block: bool, n: int
431+
self, n: int
435432
) -> tuple[ctypes.Array[INPUT_RECORD], int]:
436433
rec = (n * INPUT_RECORD)()
437434
read = DWORD()
438-
439-
if not block and not self.wait(timeout=0):
440-
return rec, 0
441-
442435
if not ReadConsoleInput(InHandle, rec, n, read):
443436
raise WinError(GetLastError())
444437

@@ -449,8 +442,11 @@ def get_event(self, block: bool = True) -> Event | None:
449442
and there is no event pending, otherwise waits for the
450443
completion of an event."""
451444

445+
if not block and not self.wait(timeout=0):
446+
return None
447+
452448
while self.event_queue.empty():
453-
rec = self._read_input(block)
449+
rec = self._read_input()
454450
if rec is None:
455451
return None
456452

@@ -551,12 +547,20 @@ def getpending(self) -> Event:
551547
if e2:
552548
e.data += e2.data
553549

554-
recs, rec_count = self._read_input_bulk(False, 1024)
550+
recs, rec_count = self._read_input_bulk(1024)
555551
for i in range(rec_count):
556552
rec = recs[i]
553+
# In case of a legacy console, we do not only receive a keydown
554+
# event, but also a keyup event - and for uppercase letters
555+
# an additional SHIFT_PRESSED event.
557556
if rec and rec.EventType == KEY_EVENT:
558557
key_event = rec.Event.KeyEvent
558+
if not key_event.bKeyDown:
559+
continue
559560
ch = key_event.uChar.UnicodeChar
561+
if ch == "\x00":
562+
# ignore SHIFT_PRESSED and special keys
563+
continue
560564
if ch == "\r":
561565
ch += "\n"
562566
e.data += ch

Lib/test/test_pyrepl/test_unix_console.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
def unix_console(events, **kwargs):
2121
console = UnixConsole()
2222
console.get_event = MagicMock(side_effect=events)
23+
console.getpending = MagicMock(return_value=Event("key", ""))
2324

2425
height = kwargs.get("height", 25)
2526
width = kwargs.get("width", 80)

Lib/test/test_pyrepl/test_windows_console.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class WindowsConsoleTests(TestCase):
3535
def console(self, events, **kwargs) -> Console:
3636
console = WindowsConsole()
3737
console.get_event = MagicMock(side_effect=events)
38+
console.getpending = MagicMock(return_value=Event("key", ""))
3839
console.wait = MagicMock()
3940
console._scroll = MagicMock()
4041
console._hide_cursor = MagicMock()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speedup pasting in ``PyREPL`` on Windows in a legacy console. Patch by Chris
2+
Eibl.

0 commit comments

Comments
 (0)