FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-111201: Allow pasted code to contain multiple statements in the REPL by pablogsal · Pull Request #118712 · python/cpython · GitHub

Repository navigation

5 changes: 4 additions & 1 deletion Lib/_pyrepl/commands.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,18 @@ def do(self) -> None:
class paste_mode(Command):

def do(self) -> None:
if not self.reader.paste_mode:
self.reader.was_paste_mode_activated = True
self.reader.paste_mode = not self.reader.paste_mode
self.reader.dirty = True


class enable_bracketed_paste(Command):
def do(self) -> None:
self.reader.paste_mode = True
self.reader.was_paste_mode_activated = True

class disable_bracketed_paste(Command):
def do(self) -> None:
self.reader.paste_mode = False
self.reader.insert("\n")
self.reader.dirty = True
1 change: 1 addition & 0 deletions Lib/_pyrepl/reader.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class Reader:
dirty: bool = False
finished: bool = False
paste_mode: bool = False
was_paste_mode_activated: bool = False
commands: dict[str, type[Command]] = field(default_factory=make_default_commands)
last_command: type[Command] | None = None
syntax_table: dict[str, int] = field(default_factory=make_default_syntax_table)
Expand Down
3 changes: 2 additions & 1 deletion Lib/_pyrepl/readline.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,11 @@ def multiline_input(self, more_lines, ps1, ps2):
reader.more_lines = more_lines
reader.ps1 = reader.ps2 = ps1
reader.ps3 = reader.ps4 = ps2
return reader.readline()
return reader.readline(), reader.was_paste_mode_activated
finally:
reader.more_lines = saved
reader.paste_mode = False
reader.was_paste_mode_activated = False

def parse_and_bind(self, string: str) -> None:
pass # XXX we don't support parsing GNU-readline-style init files
Expand Down
7 changes: 5 additions & 2 deletions Lib/_pyrepl/simple_interact.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def more_lines(unicodetext: str) -> bool:
ps1 = getattr(sys, "ps1", ">>> ")
ps2 = getattr(sys, "ps2", "... ")
try:
statement = multiline_input(more_lines, ps1, ps2)
statement, contains_pasted_code = multiline_input(more_lines, ps1, ps2)
except EOFError:
break

Expand All @@ -144,7 +144,10 @@ def more_lines(unicodetext: str) -> bool:

input_name = f"<python-input-{input_n}>"
linecache._register_code(input_name, statement, "<stdin>") # type: ignore[attr-defined]
more = console.push(_strip_final_indent(statement), filename=input_name) # type: ignore[call-arg]
symbol = "single" if not contains_pasted_code else "exec"
more = console.push(_strip_final_indent(statement), filename=input_name, _symbol=symbol) # type: ignore[call-arg]
if contains_pasted_code and more:
more = console.push(_strip_final_indent(statement), filename=input_name, _symbol="single") # type: ignore[call-arg]
assert not more
input_n += 1
except KeyboardInterrupt:
Expand Down
4 changes: 2 additions & 2 deletions Lib/code.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def interact(self, banner=None, exitmsg=None):
elif exitmsg != '':
self.write('%s\n' % exitmsg)

def push(self, line, filename=None):
def push(self, line, filename=None, _symbol="single"):
"""Push a line to the interpreter.

The line should not have a trailing newline; it may have
Expand All @@ -299,7 +299,7 @@ def push(self, line, filename=None):
source = "\n".join(self.buffer)
if filename is None:
filename = self.filename
more = self.runsource(source, filename)
more = self.runsource(source, filename, symbol=_symbol)
if not more:
self.resetbuffer()
return more
Expand Down
22 changes: 19 additions & 3 deletions Lib/test/test_pyrepl.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig
from _pyrepl.simple_interact import _strip_final_indent
from _pyrepl.unix_eventqueue import EventQueue
from _pyrepl.simple_interact import InteractiveColoredConsole


def more_lines(unicodetext, namespace=None):
Expand Down Expand Up @@ -830,7 +831,6 @@ def test_bracketed_paste(self):
' else:\n'
' pass\n'
)
# fmt: on

output_code = (
'def a():\n'
Expand All @@ -841,8 +841,8 @@ def test_bracketed_paste(self):
'\n'
' else:\n'
' pass\n'
'\n'
)
# fmt: on

paste_start = "\x1b[200~"
paste_end = "\x1b[201~"
Expand All @@ -857,6 +857,22 @@ def test_bracketed_paste(self):
output = multiline_input(reader)
self.assertEqual(output, output_code)

def test_bracketed_paste_single_line(self):
input_code = "oneline"

paste_start = "\x1b[200~"
paste_end = "\x1b[201~"

events = itertools.chain(
code_to_events(paste_start),
code_to_events(input_code),
code_to_events(paste_end),
code_to_events("\n"),
)
reader = self.prepare_reader(events)
output = multiline_input(reader)
self.assertEqual(output, input_code)


class TestReader(TestCase):
def assert_screen_equals(self, reader, expected):
Expand Down Expand Up @@ -986,5 +1002,5 @@ def test_up_arrow_after_ctrl_r(self):
self.assert_screen_equals(reader, "")


if __name__ == "__main__":
if __name__ == '__main__':

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

WHAT IS THIS

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The resistance won't be defeated

unittest.main()

Back | FazBrowse Home | New Git URL