Skip to content

Commit 16848f9

Browse files
committed
gh-133400: Fixed Ctrl+D (^D) behavior in :mod:_pyrepl module
1 parent 92337f6 commit 16848f9

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

Lib/_pyrepl/commands.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,9 @@ def do(self) -> None:
421421
r.update_screen()
422422
r.console.finish()
423423
raise EOFError
424+
elif "\n" in b and self.event[-1] == "\004":
425+
self.finish = True
426+
424427
for i in range(r.get_arg()):
425428
if r.pos != len(b):
426429
del b[r.pos]

Lib/test/test_pyrepl/test_pyrepl.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,3 +1610,43 @@ def test_prompt_after_help(self):
16101610
# Extra stuff (newline and `exit` rewrites) are necessary
16111611
# because of how run_repl works.
16121612
self.assertNotIn(">>> \n>>> >>>", cleaned_output)
1613+
1614+
class TestPyReplCtrlD(TestCase):
1615+
def prepare_reader(self, events):
1616+
console = FakeConsole(events)
1617+
config = ReadlineConfig(readline_completer=None)
1618+
reader = ReadlineAlikeReader(console=console, config=config)
1619+
return reader
1620+
1621+
def test_ctrl_d_empty_buffer(self):
1622+
"""Test that pressing Ctrl+D on empty buffer exits the program"""
1623+
events = [
1624+
Event(evt="key", data="\x04", raw=bytearray(b"\x04")), # Ctrl+D
1625+
]
1626+
reader = self.prepare_reader(events)
1627+
with self.assertRaises(EOFError):
1628+
multiline_input(reader)
1629+
1630+
def test_ctrl_d_multiline_mode(self):
1631+
"""Test that pressing Ctrl+D in multiline mode exits multiline mode"""
1632+
events = itertools.chain(
1633+
code_to_events("def f():\n"), # Enter multiline mode
1634+
[
1635+
Event(evt="key", data="\x04", raw=bytearray(b"\x04")), # Ctrl+D
1636+
],
1637+
)
1638+
reader = self.prepare_reader(events)
1639+
output = multiline_input(reader)
1640+
self.assertEqual(output, "def f():\n ") # Should return current input
1641+
1642+
def test_ctrl_d_single_line(self):
1643+
"""Test that pressing Ctrl+D in single line mode deletes current character"""
1644+
events = itertools.chain(
1645+
code_to_events("hello"),
1646+
[Event(evt="key", data="left", raw=bytearray(b"\x1bOD"))], # move left
1647+
[Event(evt="key", data="\x04", raw=bytearray(b"\x04"))], # Ctrl+D
1648+
code_to_events("\n"),
1649+
)
1650+
reader = self.prepare_reader(events)
1651+
output = multiline_input(reader)
1652+
self.assertEqual(output, "hell") # Should delete the last character
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed Ctrl+D (^D) behavior in _pyrepl module: Now properly exits multiline
2+
mode when pressed in multiline section. Added test cases to verify the
3+
behavior in both multiline and single line modes.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy