Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit5091c44

Browse files
aelsayed95ambv
andauthored
gh-118911: Trailing whitespace in a block shouldn't prevent the user from terminating the code block (#119355)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parente6572e8 commit5091c44

File tree

5 files changed

+79
-9
lines changed

5 files changed

+79
-9
lines changed

‎Lib/_pyrepl/historical_reader.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def select_item(self, i: int) -> None:
259259
self.transient_history[self.historyi]=self.get_unicode()
260260
buf=self.transient_history.get(i)
261261
ifbufisNone:
262-
buf=self.history[i]
262+
buf=self.history[i].rstrip()
263263
self.buffer=list(buf)
264264
self.historyi=i
265265
self.pos=len(self.buffer)

‎Lib/_pyrepl/readline.py‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,14 +244,27 @@ def do(self) -> None:
244244
r:ReadlineAlikeReader
245245
r=self.reader# type: ignore[assignment]
246246
r.dirty=True# this is needed to hide the completion menu, if visible
247-
#
247+
248248
# if there are already several lines and the cursor
249249
# is not on the last one, always insert a new \n.
250250
text=r.get_unicode()
251+
251252
if"\n"inr.buffer[r.pos :]or (
252253
r.more_linesisnotNoneandr.more_lines(text)
253254
):
254-
#
255+
def_newline_before_pos():
256+
before_idx=r.pos-1
257+
whilebefore_idx>0andtext[before_idx].isspace():
258+
before_idx-=1
259+
returntext[before_idx :r.pos].count("\n")>0
260+
261+
# if there's already a new line before the cursor then
262+
# even if the cursor is followed by whitespace, we assume
263+
# the user is trying to terminate the block
264+
if_newline_before_pos()andtext[r.pos:].isspace():
265+
self.finish=True
266+
return
267+
255268
# auto-indent the next line like the previous line
256269
prevlinestart,indent=_get_previous_line_indent(r.buffer,r.pos)
257270
r.insert("\n")

‎Lib/test/test_pyrepl/test_pyrepl.py‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,12 +405,21 @@ def test_multiline_edit(self):
405405
[
406406
Event(evt="key",data="up",raw=bytearray(b"\x1bOA")),
407407
Event(evt="key",data="up",raw=bytearray(b"\x1bOA")),
408-
Event(evt="key",data="up",raw=bytearray(b"\x1bOA")),
409-
Event(evt="key",data="right",raw=bytearray(b"\x1bOC")),
410-
Event(evt="key",data="backspace",raw=bytearray(b"\x7f")),
408+
Event(evt="key",data="left",raw=bytearray(b"\x1bOD")),
409+
Event(evt="key",data="left",raw=bytearray(b"\x1bOD")),
410+
Event(evt="key",data="left",raw=bytearray(b"\x1bOD")),
411+
Event(evt="key",data="backspace",raw=bytearray(b"\x08")),
411412
Event(evt="key",data="g",raw=bytearray(b"g")),
412413
Event(evt="key",data="down",raw=bytearray(b"\x1bOB")),
413-
Event(evt="key",data="down",raw=bytearray(b"\x1bOB")),
414+
Event(evt="key",data="backspace",raw=bytearray(b"\x08")),
415+
Event(evt="key",data="delete",raw=bytearray(b"\x7F")),
416+
Event(evt="key",data="right",raw=bytearray(b"g")),
417+
Event(evt="key",data="backspace",raw=bytearray(b"\x08")),
418+
Event(evt="key",data="p",raw=bytearray(b"p")),
419+
Event(evt="key",data="a",raw=bytearray(b"a")),
420+
Event(evt="key",data="s",raw=bytearray(b"s")),
421+
Event(evt="key",data="s",raw=bytearray(b"s")),
422+
Event(evt="key",data="\n",raw=bytearray(b"\n")),
414423
Event(evt="key",data="\n",raw=bytearray(b"\n")),
415424
],
416425
)
@@ -419,7 +428,7 @@ def test_multiline_edit(self):
419428
output=multiline_input(reader)
420429
self.assertEqual(output,"def f():\n ...\n ")
421430
output=multiline_input(reader)
422-
self.assertEqual(output,"def g():\n...\n ")
431+
self.assertEqual(output,"def g():\npass\n ")
423432

424433
deftest_history_navigation_with_up_arrow(self):
425434
events=itertools.chain(

‎Lib/test/test_pyrepl/test_reader.py‎

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
importitertools
2+
importfunctools
23
fromunittestimportTestCase
34

4-
from .supportimporthandle_all_events,handle_events_narrow_console,code_to_events
5+
from .supportimporthandle_all_events,handle_events_narrow_console,code_to_events,prepare_reader
56
from_pyrepl.consoleimportEvent
67

78

@@ -133,3 +134,45 @@ def test_up_arrow_after_ctrl_r(self):
133134

134135
reader,_=handle_all_events(events)
135136
self.assert_screen_equals(reader,"")
137+
138+
deftest_newline_within_block_trailing_whitespace(self):
139+
# fmt: off
140+
code= (
141+
"def foo():\n"
142+
"a = 1\n"
143+
)
144+
# fmt: on
145+
146+
events=itertools.chain(
147+
code_to_events(code),
148+
[
149+
# go to the end of the first line
150+
Event(evt="key",data="up",raw=bytearray(b"\x1bOA")),
151+
Event(evt="key",data="up",raw=bytearray(b"\x1bOA")),
152+
Event(evt="key",data="\x05",raw=bytearray(b"\x1bO5")),
153+
# new lines in-block shouldn't terminate the block
154+
Event(evt="key",data="\n",raw=bytearray(b"\n")),
155+
Event(evt="key",data="\n",raw=bytearray(b"\n")),
156+
# end of line 2
157+
Event(evt="key",data="down",raw=bytearray(b"\x1bOB")),
158+
Event(evt="key",data="\x05",raw=bytearray(b"\x1bO5")),
159+
# a double new line in-block should terminate the block
160+
# even if its followed by whitespace
161+
Event(evt="key",data="\n",raw=bytearray(b"\n")),
162+
Event(evt="key",data="\n",raw=bytearray(b"\n")),
163+
],
164+
)
165+
166+
no_paste_reader=functools.partial(prepare_reader,paste_mode=False)
167+
reader,_=handle_all_events(events,prepare_reader=no_paste_reader)
168+
169+
expected= (
170+
"def foo():\n"
171+
"\n"
172+
"\n"
173+
" a = 1\n"
174+
"\n"
175+
" "# HistoricalReader will trim trailing whitespace
176+
)
177+
self.assert_screen_equals(reader,expected)
178+
self.assertTrue(reader.finished)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
In PyREPL, updated ``maybe-accept``'s logic so that if the user hits
2+
:kbd:`Enter` twice, they are able to terminate the block even if there's
3+
trailing whitespace. Also, now when the user hits arrow up, the cursor
4+
is on the last functional line. This matches IPython's behavior.
5+
Patch by Aya Elsayed.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp