From e8b3ec8a5dd8d6e7db17ac9b80e712f4d03ae3bd Mon Sep 17 00:00:00 2001 From: Xuanteng Huang Date: Wed, 30 Jul 2025 10:23:51 +0800 Subject: [PATCH 1/5] simple fix --- Objects/frameobject.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 97de1e06efe1b2..72c0ab0666e927 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1685,6 +1685,8 @@ frame_lineno_set_impl(PyFrameObject *self, PyObject *value) case PY_MONITORING_EVENT_PY_RESUME: case PY_MONITORING_EVENT_JUMP: case PY_MONITORING_EVENT_BRANCH: + case PY_MONITORING_EVENT_BRANCH_LEFT: + case PY_MONITORING_EVENT_BRANCH_RIGHT: case PY_MONITORING_EVENT_LINE: case PY_MONITORING_EVENT_PY_YIELD: /* Setting f_lineno is allowed for the above events */ From 2e4db16adf480bffd9a2afaa77b71bafaa2756b8 Mon Sep 17 00:00:00 2001 From: Xuanteng Huang Date: Wed, 30 Jul 2025 12:26:23 +0800 Subject: [PATCH 2/5] add test --- Lib/test/test_monitoring.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index a932ac80117d27..4891bed216ec6b 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1709,6 +1709,24 @@ def func(v=1): ('branch right', 'func', 6, 8), ('branch right', 'func', 2, 10)]) + def test_callback_set_frame_lineno(self): + def func(s: str) -> int: + if s.startswith("t"): + return 1 + else: + return 0 + + def callback(code, from_, to): + frame = sys._getframe(0) + old = frame.f_lineno + # try set frame.f_lineno + frame.f_lineno = frame.f_lineno + + sys.monitoring.set_local_events(TEST_TOOL, func.__code__, E.BRANCH_LEFT) + sys.monitoring.register_callback(TEST_TOOL, E.BRANCH_LEFT, callback) + + self.assertEqual(func("true"), 1) + class TestBranchConsistency(MonitoringTestBase, unittest.TestCase): From b49f95d016ec75199cebc66bef9a06c552dd6ccf Mon Sep 17 00:00:00 2001 From: Xuanteng Huang Date: Thu, 31 Jul 2025 10:32:13 +0800 Subject: [PATCH 3/5] set lineno for frame 1 --- Lib/test/test_monitoring.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 4891bed216ec6b..25a1c09b68425e 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -3,6 +3,7 @@ import collections import dis import functools +import inspect import math import operator import sys @@ -1717,10 +1718,15 @@ def func(s: str) -> int: return 0 def callback(code, from_, to): - frame = sys._getframe(0) - old = frame.f_lineno - # try set frame.f_lineno - frame.f_lineno = frame.f_lineno + frame = inspect.currentframe() + while frame and frame.f_code is not code: + frame = frame.f_back + + if frame: + self.assertIs(frame.f_code, code) + # try get and set frame.f_lineno + l = frame.f_lineno + frame.f_lineno = l sys.monitoring.set_local_events(TEST_TOOL, func.__code__, E.BRANCH_LEFT) sys.monitoring.register_callback(TEST_TOOL, E.BRANCH_LEFT, callback) From d41cf781db89933235f20a8dd051d4b20045fad4 Mon Sep 17 00:00:00 2001 From: Xuanteng Huang Date: Thu, 31 Jul 2025 10:32:50 +0800 Subject: [PATCH 4/5] Revert "set lineno for frame 1" This reverts commit b49f95d016ec75199cebc66bef9a06c552dd6ccf. --- Lib/test/test_monitoring.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 25a1c09b68425e..4891bed216ec6b 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -3,7 +3,6 @@ import collections import dis import functools -import inspect import math import operator import sys @@ -1718,15 +1717,10 @@ def func(s: str) -> int: return 0 def callback(code, from_, to): - frame = inspect.currentframe() - while frame and frame.f_code is not code: - frame = frame.f_back - - if frame: - self.assertIs(frame.f_code, code) - # try get and set frame.f_lineno - l = frame.f_lineno - frame.f_lineno = l + frame = sys._getframe(0) + old = frame.f_lineno + # try set frame.f_lineno + frame.f_lineno = frame.f_lineno sys.monitoring.set_local_events(TEST_TOOL, func.__code__, E.BRANCH_LEFT) sys.monitoring.register_callback(TEST_TOOL, E.BRANCH_LEFT, callback) From b8e9f12c764a861727f0f45e5e5075182922f4ff Mon Sep 17 00:00:00 2001 From: Xuanteng Huang Date: Thu, 31 Jul 2025 10:41:26 +0800 Subject: [PATCH 5/5] fix test --- Lib/test/test_monitoring.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 4891bed216ec6b..4122f786a9afb0 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -3,6 +3,7 @@ import collections import dis import functools +import inspect import math import operator import sys @@ -1717,10 +1718,13 @@ def func(s: str) -> int: return 0 def callback(code, from_, to): - frame = sys._getframe(0) - old = frame.f_lineno # try set frame.f_lineno - frame.f_lineno = frame.f_lineno + frame = inspect.currentframe() + while frame and frame.f_code is not code: + frame = frame.f_back + + self.assertIsNotNone(frame) + frame.f_lineno = frame.f_lineno + 1 # run next instruction sys.monitoring.set_local_events(TEST_TOOL, func.__code__, E.BRANCH_LEFT) sys.monitoring.register_callback(TEST_TOOL, E.BRANCH_LEFT, callback)