Skip to content

Commit a738745

Browse files
gh-152966: Split the source into lines at newlines only
str.splitlines() also breaks at form feed and similar characters that the compiler and the Text widget keep within the line, which misaligned the column mapping for the following lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 11b9bcd commit a738745

2 files changed

Lines changed: 13 additions & 2 deletions

File tree

Lib/idlelib/disbrowser.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ def populate(self, event=None):
218218
first, scope = "1.0", "text"
219219
self.base = tuple(int(i) for i in first.split("."))
220220
source = text.get(first, last)
221-
self.source_lines = source.splitlines()
221+
# Split at "\n" only; str.splitlines() would also break at "\f" etc.
222+
self.source_lines = source.split("\n")
222223
error = None
223224
try:
224225
code = compile(source, "<disassembly>", "exec")
@@ -346,7 +347,7 @@ def show_running(self, code, offset):
346347
# Positions map to the editor only when it shows this frame's file.
347348
self.map_source = self.editor_shows(code.co_filename)
348349
if self.map_source:
349-
self.source_lines = self.text.get("1.0", "end-1c").splitlines()
350+
self.source_lines = self.text.get("1.0", "end-1c").split("\n")
350351
self.add_code(code) # The frame's own code is the first top-level row.
351352
self.mark_current(offset)
352353
self.status.configure(

Lib/idlelib/idle_test/test_disbrowser.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ def test_instruction_range(self):
123123
item = self.instr_at(("4.11", "4.12"))
124124
self.assertEqual(self.window.tree.set(item, "arg"), "x")
125125

126+
def test_form_feed_does_not_shift_lines(self):
127+
# gh-152966: a form feed breaks str.splitlines() but not the compiler,
128+
# so it must not shift source_lines and misplace later instructions.
129+
window = self.window
130+
self.text.delete("1.0", "end")
131+
self.text.insert("1.0", "a = 1\f\nb = 22\n") # form feed ends line 1.
132+
window.populate()
133+
ranges = [window.ranges[it] for it in window.instr_items]
134+
self.assertIn(("2.4", "2.6"), ranges) # the load of 22.
135+
126136
def code_node(self, qualname):
127137
"Return the top-level code-object row named qualname."
128138
tree = self.window.tree

0 commit comments

Comments
 (0)