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

Appearance settings

Commit 2bf7475

Browse filesBrowse files
authored
GH-93662: Make sure that column offsets are correct in multi-line method calls. (GH-93673)
1 parent 4caf5c2 commit 2bf7475
Copy full SHA for 2bf7475

File tree

Expand file treeCollapse file tree

3 files changed

+48
-5
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+48
-5
lines changed

‎Lib/test/test_code.py

Copy file name to clipboardExpand all lines: Lib/test/test_code.py
+30-1Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,15 @@ def positions_from_location_table(code):
574574
for _ in range(length):
575575
yield (line, end_line, col, end_col)
576576

577+
def dedup(lst, prev=object()):
578+
for item in lst:
579+
if item != prev:
580+
yield item
581+
prev = item
582+
583+
def lines_from_postions(positions):
584+
return dedup(l for (l, _, _, _) in positions)
585+
577586
def misshappen():
578587
"""
579588
@@ -606,6 +615,13 @@ def misshappen():
606615

607616
) else p
608617

618+
def bug93662():
619+
example_report_generation_message= (
620+
"""
621+
"""
622+
).strip()
623+
raise ValueError()
624+
609625

610626
class CodeLocationTest(unittest.TestCase):
611627

@@ -616,10 +632,23 @@ def check_positions(self, func):
616632
self.assertEqual(l1, l2)
617633
self.assertEqual(len(pos1), len(pos2))
618634

619-
620635
def test_positions(self):
621636
self.check_positions(parse_location_table)
622637
self.check_positions(misshappen)
638+
self.check_positions(bug93662)
639+
640+
def check_lines(self, func):
641+
co = func.__code__
642+
lines1 = list(dedup(l for (_, _, l) in co.co_lines()))
643+
lines2 = list(lines_from_postions(positions_from_location_table(co)))
644+
for l1, l2 in zip(lines1, lines2):
645+
self.assertEqual(l1, l2)
646+
self.assertEqual(len(lines1), len(lines2))
647+
648+
def test_lines(self):
649+
self.check_lines(parse_location_table)
650+
self.check_lines(misshappen)
651+
self.check_lines(bug93662)
623652

624653

625654
if check_impl_detail(cpython=True) and ctypes is not None:
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make sure that the end column offsets are correct in multi-line method
2+
calls. Previously, the end column could precede the column offset.

‎Python/compile.c

Copy file name to clipboardExpand all lines: Python/compile.c
+16-4Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4801,6 +4801,16 @@ is_import_originated(struct compiler *c, expr_ty e)
48014801
return flags & DEF_IMPORT;
48024802
}
48034803

4804+
static void
4805+
update_location_to_match_attr(struct compiler *c, expr_ty meth)
4806+
{
4807+
if (meth->lineno != meth->end_lineno) {
4808+
// Make start location match attribute
4809+
c->u->u_lineno = meth->end_lineno;
4810+
c->u->u_col_offset = meth->end_col_offset - (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1;
4811+
}
4812+
}
4813+
48044814
// Return 1 if the method call was optimized, -1 if not, and 0 on error.
48054815
static int
48064816
maybe_optimize_method_call(struct compiler *c, expr_ty e)
@@ -4842,8 +4852,8 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
48424852
}
48434853
/* Alright, we can optimize the code. */
48444854
VISIT(c, expr, meth->v.Attribute.value);
4845-
int old_lineno = c->u->u_lineno;
4846-
c->u->u_lineno = meth->end_lineno;
4855+
SET_LOC(c, meth);
4856+
update_location_to_match_attr(c, meth);
48474857
ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names);
48484858
VISIT_SEQ(c, expr, e->v.Call.args);
48494859

@@ -4853,8 +4863,9 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
48534863
return 0;
48544864
};
48554865
}
4866+
SET_LOC(c, e);
4867+
update_location_to_match_attr(c, meth);
48564868
ADDOP_I(c, CALL, argsl + kwdsl);
4857-
c->u->u_lineno = old_lineno;
48584869
return 1;
48594870
}
48604871

@@ -7673,6 +7684,7 @@ write_location_info_short_form(struct assembler* a, int length, int column, int
76737684
int column_low_bits = column & 7;
76747685
int column_group = column >> 3;
76757686
assert(column < 80);
7687+
assert(end_column >= column);
76767688
assert(end_column - column < 16);
76777689
write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
76787690
write_location_byte(a, (column_low_bits << 4) | (end_column - column));
@@ -7744,7 +7756,7 @@ write_location_info_entry(struct assembler* a, struct instr* i, int isize)
77447756
}
77457757
}
77467758
else if (i->i_end_lineno == i->i_lineno) {
7747-
if (line_delta == 0 && column < 80 && end_column - column < 16) {
7759+
if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {
77487760
write_location_info_short_form(a, isize, column, end_column);
77497761
return 1;
77507762
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.