]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-130328: Speedup pasting in legacy console on Windows (gh-133728)
authorChris Eibl <138194463+chris-eibl@users.noreply.github.com>
Sun, 25 May 2025 13:17:43 +0000 (15:17 +0200)
committerGitHub <noreply@github.com>
Sun, 25 May 2025 13:17:43 +0000 (15:17 +0200)
Lib/_pyrepl/commands.py
Lib/_pyrepl/windows_console.py
Lib/test/test_pyrepl/test_unix_console.py
Lib/test/test_pyrepl/test_windows_console.py
Misc/NEWS.d/next/Library/2025-05-09-09-10-34.gh-issue-130328.s9h4By.rst [new file with mode: 0644]

index 2354fbb2ec2c1eac4ff0f4b522e9a75aebc2a257..50c824995d85b8bc411f6613fe18b3766de02be3 100644 (file)
@@ -370,6 +370,13 @@ class self_insert(EditCommand):
         r = self.reader
         text = self.event * r.get_arg()
         r.insert(text)
+        if r.paste_mode:
+            data = ""
+            ev = r.console.getpending()
+            data += ev.data
+            if data:
+                r.insert(data)
+                r.last_refresh_cache.invalidated = True
 
 
 class insert_nl(EditCommand):
@@ -484,7 +491,6 @@ class perform_bracketed_paste(Command):
         data = ""
         start = time.time()
         while done not in data:
-            self.reader.console.wait(100)
             ev = self.reader.console.getpending()
             data += ev.data
         trace(
index 95749198b3b2f9664a7c3b35930039644cdf1a27..c56dcd6d7dd434f1c8fa8b2c998eb3888a3a6939 100644 (file)
@@ -419,10 +419,7 @@ 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 and not self.wait(timeout=0):
-            return None
-
+    def _read_input(self) -> INPUT_RECORD | None:
         rec = INPUT_RECORD()
         read = DWORD()
         if not ReadConsoleInput(InHandle, rec, 1, read):
@@ -431,14 +428,10 @@ class WindowsConsole(Console):
         return rec
 
     def _read_input_bulk(
-        self, block: bool, n: int
+        self, n: int
     ) -> tuple[ctypes.Array[INPUT_RECORD], int]:
         rec = (n * INPUT_RECORD)()
         read = DWORD()
-
-        if not block and not self.wait(timeout=0):
-            return rec, 0
-
         if not ReadConsoleInput(InHandle, rec, n, read):
             raise WinError(GetLastError())
 
@@ -449,8 +442,11 @@ class WindowsConsole(Console):
         and there is no event pending, otherwise waits for the
         completion of an event."""
 
+        if not block and not self.wait(timeout=0):
+            return None
+
         while self.event_queue.empty():
-            rec = self._read_input(block)
+            rec = self._read_input()
             if rec is None:
                 return None
 
@@ -551,12 +547,20 @@ class WindowsConsole(Console):
             if e2:
                 e.data += e2.data
 
-        recs, rec_count = self._read_input_bulk(False, 1024)
+        recs, rec_count = self._read_input_bulk(1024)
         for i in range(rec_count):
             rec = recs[i]
+            # In case of a legacy console, we do not only receive a keydown
+            # event, but also a keyup event - and for uppercase letters
+            # an additional SHIFT_PRESSED event.
             if rec and rec.EventType == KEY_EVENT:
                 key_event = rec.Event.KeyEvent
+                if not key_event.bKeyDown:
+                    continue
                 ch = key_event.uChar.UnicodeChar
+                if ch == "\x00":
+                    # ignore SHIFT_PRESSED and special keys
+                    continue
                 if ch == "\r":
                     ch += "\n"
                 e.data += ch
index c447b310c49a0629bf16f3e5ef4f172359592edf..b3f7dc028fe21020da2bf2b8f33143b9372390db 100644 (file)
@@ -20,6 +20,7 @@ except ImportError:
 def unix_console(events, **kwargs):
     console = UnixConsole()
     console.get_event = MagicMock(side_effect=events)
+    console.getpending = MagicMock(return_value=Event("key", ""))
 
     height = kwargs.get("height", 25)
     width = kwargs.get("width", 80)
index e7bab226b31ddf15ca3975944e0c99d4342c141f..a52ae96a83ddde372d2285667d8365d6cea8d28f 100644 (file)
@@ -35,6 +35,7 @@ class WindowsConsoleTests(TestCase):
     def console(self, events, **kwargs) -> Console:
         console = WindowsConsole()
         console.get_event = MagicMock(side_effect=events)
+        console.getpending = MagicMock(return_value=Event("key", ""))
         console.wait = MagicMock()
         console._scroll = MagicMock()
         console._hide_cursor = MagicMock()
diff --git a/Misc/NEWS.d/next/Library/2025-05-09-09-10-34.gh-issue-130328.s9h4By.rst b/Misc/NEWS.d/next/Library/2025-05-09-09-10-34.gh-issue-130328.s9h4By.rst
new file mode 100644 (file)
index 0000000..00b556c
--- /dev/null
@@ -0,0 +1,2 @@
+Speedup pasting in ``PyREPL`` on Windows in a legacy console. Patch by Chris
+Eibl.