diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 1bb138e7f3243b..a6857dc4f84120 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -574,6 +574,15 @@ def positions_from_location_table(code): for _ in range(length): yield (line, end_line, col, end_col) +def dedup(lst, prev=object()): + for item in lst: + if item != prev: + yield item + prev = item + +def lines_from_postions(positions): + return dedup(l for (l, _, _, _) in positions) + def misshappen(): """ @@ -606,6 +615,13 @@ def misshappen(): ) else p +def bug93662(): + example_report_generation_message= ( + """ + """ + ).strip() + raise ValueError() + class CodeLocationTest(unittest.TestCase): @@ -616,10 +632,23 @@ def check_positions(self, func): self.assertEqual(l1, l2) self.assertEqual(len(pos1), len(pos2)) - def test_positions(self): self.check_positions(parse_location_table) self.check_positions(misshappen) + self.check_positions(bug93662) + + def check_lines(self, func): + co = func.__code__ + lines1 = list(dedup(l for (_, _, l) in co.co_lines())) + lines2 = list(lines_from_postions(positions_from_location_table(co))) + for l1, l2 in zip(lines1, lines2): + self.assertEqual(l1, l2) + self.assertEqual(len(lines1), len(lines2)) + + def test_lines(self): + self.check_lines(parse_location_table) + self.check_lines(misshappen) + self.check_lines(bug93662) if check_impl_detail(cpython=True) and ctypes is not None: diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-10-10-31-18.gh-issue-93662.-7RSC1.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-10-10-31-18.gh-issue-93662.-7RSC1.rst new file mode 100644 index 00000000000000..e444a00cf7ecc0 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-10-10-31-18.gh-issue-93662.-7RSC1.rst @@ -0,0 +1,2 @@ +Make sure that the end column offsets are correct in multi-line method +calls. Previously, the end column could precede the column offset. diff --git a/Python/compile.c b/Python/compile.c index bbd71936cf3468..cdaf7d9c07635b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -4801,6 +4801,16 @@ is_import_originated(struct compiler *c, expr_ty e) return flags & DEF_IMPORT; } +static void +update_location_to_match_attr(struct compiler *c, expr_ty meth) +{ + if (meth->lineno != meth->end_lineno) { + // Make start location match attribute + c->u->u_lineno = meth->end_lineno; + c->u->u_col_offset = meth->end_col_offset - (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1; + } +} + // Return 1 if the method call was optimized, -1 if not, and 0 on error. static int maybe_optimize_method_call(struct compiler *c, expr_ty e) @@ -4842,8 +4852,8 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) } /* Alright, we can optimize the code. */ VISIT(c, expr, meth->v.Attribute.value); - int old_lineno = c->u->u_lineno; - c->u->u_lineno = meth->end_lineno; + SET_LOC(c, meth); + update_location_to_match_attr(c, meth); ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names); VISIT_SEQ(c, expr, e->v.Call.args); @@ -4853,8 +4863,9 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) return 0; }; } + SET_LOC(c, e); + update_location_to_match_attr(c, meth); ADDOP_I(c, CALL, argsl + kwdsl); - c->u->u_lineno = old_lineno; return 1; } @@ -7667,6 +7678,7 @@ write_location_info_short_form(struct assembler* a, int length, int column, int int column_low_bits = column & 7; int column_group = column >> 3; assert(column < 80); + assert(end_column >= column); assert(end_column - column < 16); write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length); write_location_byte(a, (column_low_bits << 4) | (end_column - column)); @@ -7738,7 +7750,7 @@ write_location_info_entry(struct assembler* a, struct instr* i, int isize) } } else if (i->i_end_lineno == i->i_lineno) { - if (line_delta == 0 && column < 80 && end_column - column < 16) { + if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) { write_location_info_short_form(a, isize, column, end_column); return 1; } 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