Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e6572e8

Browse filesBrowse files
pablogsalambv
andauthored
gh-111201: Speed up paste mode in the REPL (#119341)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parent cd516cd commit e6572e8
Copy full SHA for e6572e8

File tree

6 files changed

+21
-16
lines changed
Filter options

6 files changed

+21
-16
lines changed

‎Lib/_pyrepl/commands.py

Copy file name to clipboardExpand all lines: Lib/_pyrepl/commands.py
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,18 +461,17 @@ def do(self) -> None:
461461
class paste_mode(Command):
462462

463463
def do(self) -> None:
464-
if not self.reader.paste_mode:
465-
self.reader.was_paste_mode_activated = True
466464
self.reader.paste_mode = not self.reader.paste_mode
467465
self.reader.dirty = True
468466

469467

470468
class enable_bracketed_paste(Command):
471469
def do(self) -> None:
472470
self.reader.paste_mode = True
473-
self.reader.was_paste_mode_activated = True
471+
self.reader.in_bracketed_paste = True
474472

475473
class disable_bracketed_paste(Command):
476474
def do(self) -> None:
477475
self.reader.paste_mode = False
476+
self.reader.in_bracketed_paste = False
478477
self.reader.dirty = True

‎Lib/_pyrepl/reader.py

Copy file name to clipboardExpand all lines: Lib/_pyrepl/reader.py
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def disp_str(buffer: str) -> tuple[str, list[int]]:
5454
b: list[int] = []
5555
s: list[str] = []
5656
for c in buffer:
57-
if unicodedata.category(c).startswith("C"):
57+
if ord(c) > 128 and unicodedata.category(c).startswith("C"):
5858
c = r"\u%04x" % ord(c)
5959
s.append(c)
6060
b.append(wlen(c))
@@ -225,7 +225,7 @@ class Reader:
225225
dirty: bool = False
226226
finished: bool = False
227227
paste_mode: bool = False
228-
was_paste_mode_activated: bool = False
228+
in_bracketed_paste: bool = False
229229
commands: dict[str, type[Command]] = field(default_factory=make_default_commands)
230230
last_command: type[Command] | None = None
231231
syntax_table: dict[str, int] = field(default_factory=make_default_syntax_table)
@@ -448,7 +448,7 @@ def get_prompt(self, lineno: int, cursor_on_line: bool) -> str:
448448
elif "\n" in self.buffer:
449449
if lineno == 0:
450450
prompt = self.ps2
451-
elif lineno == self.buffer.count("\n"):
451+
elif self.ps4 and lineno == self.buffer.count("\n"):
452452
prompt = self.ps4
453453
else:
454454
prompt = self.ps3
@@ -611,7 +611,7 @@ def do_cmd(self, cmd: tuple[str, list[str]]) -> None:
611611

612612
self.after_command(command)
613613

614-
if self.dirty:
614+
if self.dirty and not self.in_bracketed_paste:
615615
self.refresh()
616616
else:
617617
self.update_cursor()

‎Lib/_pyrepl/readline.py

Copy file name to clipboardExpand all lines: Lib/_pyrepl/readline.py
+6-5Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def input(self, prompt: object = "") -> str:
328328
reader.ps1 = str(prompt)
329329
return reader.readline(startup_hook=self.startup_hook)
330330

331-
def multiline_input(self, more_lines: MoreLinesCallable, ps1: str, ps2: str) -> tuple[str, bool]:
331+
def multiline_input(self, more_lines: MoreLinesCallable, ps1: str, ps2: str) -> str:
332332
"""Read an input on possibly multiple lines, asking for more
333333
lines as long as 'more_lines(unicodetext)' returns an object whose
334334
boolean value is true.
@@ -337,14 +337,15 @@ def multiline_input(self, more_lines: MoreLinesCallable, ps1: str, ps2: str) ->
337337
saved = reader.more_lines
338338
try:
339339
reader.more_lines = more_lines
340-
reader.ps1 = reader.ps2 = ps1
341-
reader.ps3 = reader.ps4 = ps2
340+
reader.ps1 = ps1
341+
reader.ps2 = ps1
342+
reader.ps3 = ps2
343+
reader.ps4 = ""
342344
with warnings.catch_warnings(action="ignore"):
343-
return reader.readline(), reader.was_paste_mode_activated
345+
return reader.readline()
344346
finally:
345347
reader.more_lines = saved
346348
reader.paste_mode = False
347-
reader.was_paste_mode_activated = False
348349

349350
def parse_and_bind(self, string: str) -> None:
350351
pass # XXX we don't support parsing GNU-readline-style init files

‎Lib/_pyrepl/simple_interact.py

Copy file name to clipboardExpand all lines: Lib/_pyrepl/simple_interact.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def _strip_final_indent(text: str) -> str:
6262
"quit": _sitebuiltins.Quitter('quit' ,''),
6363
"copyright": _sitebuiltins._Printer('copyright', sys.copyright),
6464
"help": "help",
65+
"clear": "clear_screen",
6566
}
6667

6768
class InteractiveColoredConsole(code.InteractiveConsole):
@@ -163,7 +164,7 @@ def more_lines(unicodetext: str) -> bool:
163164
ps1 = getattr(sys, "ps1", ">>> ")
164165
ps2 = getattr(sys, "ps2", "... ")
165166
try:
166-
statement, contains_pasted_code = multiline_input(more_lines, ps1, ps2)
167+
statement = multiline_input(more_lines, ps1, ps2)
167168
except EOFError:
168169
break
169170

‎Lib/_pyrepl/utils.py

Copy file name to clipboard
+6-2Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import re
22
import unicodedata
3+
import functools
34

45
ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]")
56

67

8+
@functools.cache
79
def str_width(c: str) -> int:
10+
if ord(c) < 128:
11+
return 1
812
w = unicodedata.east_asian_width(c)
913
if w in ('N', 'Na', 'H', 'A'):
1014
return 1
@@ -13,6 +17,6 @@ def str_width(c: str) -> int:
1317

1418
def wlen(s: str) -> int:
1519
length = sum(str_width(i) for i in s)
16-
1720
# remove lengths of any escape sequences
18-
return length - sum(len(i) for i in ANSI_ESCAPE_SEQUENCE.findall(s))
21+
sequence = ANSI_ESCAPE_SEQUENCE.findall(s)
22+
return length - sum(len(i) for i in sequence)

‎Lib/test/test_pyrepl/test_pyrepl.py

Copy file name to clipboardExpand all lines: Lib/test/test_pyrepl/test_pyrepl.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ def test_func(self):
578578
reader = self.prepare_reader(events, namespace)
579579
mock_get_reader.return_value = reader
580580
output = readline_multiline_input(more_lines, ">>>", "...")
581-
self.assertEqual(output[0], "dummy.test_func.__")
581+
self.assertEqual(output, "dummy.test_func.__")
582582
self.assertEqual(mock_stderr.getvalue(), "")
583583

584584

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.