gh-111201: Allow pasted code to contain multiple statements in the REPL by pablogsal · Pull Request #118712 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Lib/_pyrepl/commands.py
1 change: 1 addition & 0 deletions Lib/_pyrepl/reader.py
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
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
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
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