44import functools
55import operator
66import sys
7+ import textwrap
78import types
89import unittest
910
@@ -506,7 +507,7 @@ def test_lines_single(self):
506507 sys .monitoring .set_events (TEST_TOOL , 0 )
507508 sys .monitoring .register_callback (TEST_TOOL , E .LINE , None )
508509 start = LineMonitoringTest .test_lines_single .__code__ .co_firstlineno
509- self .assertEqual (events , [start + 7 , 14 , start + 8 ])
510+ self .assertEqual (events , [start + 7 , 15 , start + 8 ])
510511 finally :
511512 sys .monitoring .set_events (TEST_TOOL , 0 )
512513 sys .monitoring .register_callback (TEST_TOOL , E .LINE , None )
@@ -524,7 +525,7 @@ def test_lines_loop(self):
524525 sys .monitoring .set_events (TEST_TOOL , 0 )
525526 sys .monitoring .register_callback (TEST_TOOL , E .LINE , None )
526527 start = LineMonitoringTest .test_lines_loop .__code__ .co_firstlineno
527- self .assertEqual (events , [start + 7 , 21 , 22 , 22 , 21 , start + 8 ])
528+ self .assertEqual (events , [start + 7 , 22 , 23 , 23 , 22 , start + 8 ])
528529 finally :
529530 sys .monitoring .set_events (TEST_TOOL , 0 )
530531 sys .monitoring .register_callback (TEST_TOOL , E .LINE , None )
@@ -546,7 +547,7 @@ def test_lines_two(self):
546547 sys .monitoring .register_callback (TEST_TOOL , E .LINE , None )
547548 sys .monitoring .register_callback (TEST_TOOL2 , E .LINE , None )
548549 start = LineMonitoringTest .test_lines_two .__code__ .co_firstlineno
549- expected = [start + 10 , 14 , start + 11 ]
550+ expected = [start + 10 , 15 , start + 11 ]
550551 self .assertEqual (events , expected )
551552 self .assertEqual (events2 , expected )
552553 finally :
@@ -1082,6 +1083,99 @@ def func():
10821083 ('line' , 'check_events' , 11 )])
10831084
10841085
1086+ class TestLoadSuperAttr (CheckEvents ):
1087+ def _super_method_call (self , optimized = False ):
1088+ assignment = "x = 1" if optimized else "super = super"
1089+ codestr = textwrap .dedent (f"""
1090+ { assignment }
1091+ class A:
1092+ def method(self, x):
1093+ return x
1094+
1095+ class B(A):
1096+ def method(self, x):
1097+ return super(
1098+ ).method(
1099+ x
1100+ )
1101+
1102+ b = B()
1103+ def f():
1104+ return b.method(1)
1105+ """ )
1106+ d = {}
1107+ exec (codestr , d , d )
1108+ expected = [
1109+ ('line' , 'check_events' , 10 ),
1110+ ('call' , 'f' , sys .monitoring .MISSING ),
1111+ ('line' , 'f' , 1 ),
1112+ ('call' , 'method' , d ["b" ]),
1113+ ('line' , 'method' , 1 ),
1114+ ('call' , 'super' , sys .monitoring .MISSING ),
1115+ ('C return' , 'super' , sys .monitoring .MISSING ),
1116+ ('line' , 'method' , 2 ),
1117+ ('line' , 'method' , 3 ),
1118+ ('line' , 'method' , 2 ),
1119+ ('call' , 'method' , 1 ),
1120+ ('line' , 'method' , 1 ),
1121+ ('line' , 'method' , 1 ),
1122+ ('line' , 'check_events' , 11 ),
1123+ ('call' , 'set_events' , 2 ),
1124+ ]
1125+ return d ["f" ], expected
1126+
1127+ def test_method_call (self ):
1128+ nonopt_func , nonopt_expected = self ._super_method_call (optimized = False )
1129+ opt_func , opt_expected = self ._super_method_call (optimized = True )
1130+
1131+ recorders = CallRecorder , LineRecorder , CRaiseRecorder , CReturnRecorder
1132+
1133+ self .check_events (nonopt_func , recorders = recorders , expected = nonopt_expected )
1134+ self .check_events (opt_func , recorders = recorders , expected = opt_expected )
1135+
1136+ def _super_attr (self , optimized = False ):
1137+ assignment = "x = 1" if optimized else "super = super"
1138+ codestr = textwrap .dedent (f"""
1139+ { assignment }
1140+ class A:
1141+ x = 1
1142+
1143+ class B(A):
1144+ def method(self):
1145+ return super(
1146+ ).x
1147+
1148+ b = B()
1149+ def f():
1150+ return b.method()
1151+ """ )
1152+ d = {}
1153+ exec (codestr , d , d )
1154+ expected = [
1155+ ('line' , 'check_events' , 10 ),
1156+ ('call' , 'f' , sys .monitoring .MISSING ),
1157+ ('line' , 'f' , 1 ),
1158+ ('call' , 'method' , d ["b" ]),
1159+ ('line' , 'method' , 1 ),
1160+ ('call' , 'super' , sys .monitoring .MISSING ),
1161+ ('C return' , 'super' , sys .monitoring .MISSING ),
1162+ ('line' , 'method' , 2 ),
1163+ ('line' , 'method' , 1 ),
1164+ ('line' , 'check_events' , 11 ),
1165+ ('call' , 'set_events' , 2 )
1166+ ]
1167+ return d ["f" ], expected
1168+
1169+ def test_attr (self ):
1170+ nonopt_func , nonopt_expected = self ._super_attr (optimized = False )
1171+ opt_func , opt_expected = self ._super_attr (optimized = True )
1172+
1173+ recorders = CallRecorder , LineRecorder , CRaiseRecorder , CReturnRecorder
1174+
1175+ self .check_events (nonopt_func , recorders = recorders , expected = nonopt_expected )
1176+ self .check_events (opt_func , recorders = recorders , expected = opt_expected )
1177+
1178+
10851179class TestSetGetEvents (MonitoringTestBase , unittest .TestCase ):
10861180
10871181 def test_global (self ):
0 commit comments