mirror of https://github.com/python/cpython
[3.13] gh-93691: fix too broad source locations of with-statement instructions (GH-120125) (#123604)
gh-93691: fix too broad source locations of with-statement instructions (GH-120125)
(cherry picked from commit eca3f7762c
)
Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
This commit is contained in:
parent
3b3a1a8e7e
commit
494181e44d
|
@ -5,6 +5,7 @@ __author__ = "Mike Bland"
|
||||||
__email__ = "mbland at acm dot org"
|
__email__ = "mbland at acm dot org"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
import unittest
|
import unittest
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from contextlib import _GeneratorContextManager, contextmanager, nullcontext
|
from contextlib import _GeneratorContextManager, contextmanager, nullcontext
|
||||||
|
@ -749,5 +750,48 @@ class NestedWith(unittest.TestCase):
|
||||||
self.assertEqual(10, b1)
|
self.assertEqual(10, b1)
|
||||||
self.assertEqual(20, b2)
|
self.assertEqual(20, b2)
|
||||||
|
|
||||||
|
def testExceptionLocation(self):
|
||||||
|
# The location of an exception raised from
|
||||||
|
# __init__, __enter__ or __exit__ of a context
|
||||||
|
# manager should be just the context manager expression,
|
||||||
|
# pinpointing the precise context manager in case there
|
||||||
|
# is more than one.
|
||||||
|
|
||||||
|
def init_raises():
|
||||||
|
try:
|
||||||
|
with self.Dummy(), self.InitRaises() as cm, self.Dummy() as d:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
return e
|
||||||
|
|
||||||
|
def enter_raises():
|
||||||
|
try:
|
||||||
|
with self.EnterRaises(), self.Dummy() as d:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
return e
|
||||||
|
|
||||||
|
def exit_raises():
|
||||||
|
try:
|
||||||
|
with self.ExitRaises(), self.Dummy() as d:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
return e
|
||||||
|
|
||||||
|
for func, expected in [(init_raises, "self.InitRaises()"),
|
||||||
|
(enter_raises, "self.EnterRaises()"),
|
||||||
|
(exit_raises, "self.ExitRaises()"),
|
||||||
|
]:
|
||||||
|
with self.subTest(func):
|
||||||
|
exc = func()
|
||||||
|
f = traceback.extract_tb(exc.__traceback__)[0]
|
||||||
|
indent = 16
|
||||||
|
co = func.__code__
|
||||||
|
self.assertEqual(f.lineno, co.co_firstlineno + 2)
|
||||||
|
self.assertEqual(f.end_lineno, co.co_firstlineno + 2)
|
||||||
|
self.assertEqual(f.line[f.colno - indent : f.end_colno - indent],
|
||||||
|
expected)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix source locations of instructions generated for with statements.
|
|
@ -6036,7 +6036,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
|
|
||||||
/* Evaluate EXPR */
|
/* Evaluate EXPR */
|
||||||
VISIT(c, expr, item->context_expr);
|
VISIT(c, expr, item->context_expr);
|
||||||
|
loc = LOC(item->context_expr);
|
||||||
ADDOP(c, loc, BEFORE_ASYNC_WITH);
|
ADDOP(c, loc, BEFORE_ASYNC_WITH);
|
||||||
ADDOP_I(c, loc, GET_AWAITABLE, 1);
|
ADDOP_I(c, loc, GET_AWAITABLE, 1);
|
||||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||||
|
@ -6134,7 +6134,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
/* Evaluate EXPR */
|
/* Evaluate EXPR */
|
||||||
VISIT(c, expr, item->context_expr);
|
VISIT(c, expr, item->context_expr);
|
||||||
/* Will push bound __exit__ */
|
/* Will push bound __exit__ */
|
||||||
location loc = LOC(s);
|
location loc = LOC(item->context_expr);
|
||||||
ADDOP(c, loc, BEFORE_WITH);
|
ADDOP(c, loc, BEFORE_WITH);
|
||||||
ADDOP_JUMP(c, loc, SETUP_WITH, final);
|
ADDOP_JUMP(c, loc, SETUP_WITH, final);
|
||||||
|
|
||||||
|
@ -6167,7 +6167,6 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
/* For successful outcome:
|
/* For successful outcome:
|
||||||
* call __exit__(None, None, None)
|
* call __exit__(None, None, None)
|
||||||
*/
|
*/
|
||||||
loc = LOC(s);
|
|
||||||
RETURN_IF_ERROR(compiler_call_exit_with_nones(c, loc));
|
RETURN_IF_ERROR(compiler_call_exit_with_nones(c, loc));
|
||||||
ADDOP(c, loc, POP_TOP);
|
ADDOP(c, loc, POP_TOP);
|
||||||
ADDOP_JUMP(c, loc, JUMP, exit);
|
ADDOP_JUMP(c, loc, JUMP, exit);
|
||||||
|
|
Loading…
Reference in New Issue