from test
import test_support
def callback(self
, frame
, event
, arg
):
or event
== "exception"):
self
.add_event(event
, frame
)
def add_event(self
, event
, frame
=None):
"""Add an event to the log."""
frameno
= self
.frames
.index(frame
)
frameno
= len(self
.frames
)
self
.frames
.append(frame
)
self
.events
.append((frameno
, event
, ident(frame
)))
"""Remove calls to add_event()."""
disallowed
= [ident(self
.add_event
.im_func
), ident(ident
)]
return [item
for item
in self
.events
if item
[2] not in disallowed
]
class ProfileSimulator(HookWatcher
):
def __init__(self
, testcase
):
HookWatcher
.__init
__(self
)
def callback(self
, frame
, event
, arg
):
# Callback registered with sys.setprofile()/sys.settrace()
self
.dispatch
[event
](self
, frame
)
def trace_call(self
, frame
):
self
.add_event('call', frame
)
def trace_return(self
, frame
):
self
.add_event('return', frame
)
def trace_exception(self
, frame
):
"the profiler should never receive exception events")
def trace_pass(self
, frame
):
'exception': trace_exception
,
'c_exception': trace_pass
,
class TestCaseBase(unittest
.TestCase
):
def check_events(self
, callable, expected
):
events
= capture_events(callable, self
.new_watcher())
self
.fail("Expected events:\n%s\nReceived events:\n%s"
% (pprint
.pformat(expected
), pprint
.pformat(events
)))
class ProfileHookTestCase(TestCaseBase
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_exception(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_caught_exception(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_caught_nested_exception(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_nested_exception(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
# This isn't what I expected:
# (0, 'exception', protect_ident),
def test_exception_in_except_clause(self
):
self
.check_events(g
, [(1, 'call', g_ident
),
def test_exception_propogation(self
):
finally: p
.add_event("falling through")
self
.check_events(g
, [(1, 'call', g_ident
),
(1, 'falling through', g_ident
),
def test_raise_twice(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_raise_reraise(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
self
.check_events(f
, [(1, 'call', f_ident
),
def test_distant_exception(self
):
self
.check_events(j
, [(1, 'call', j_ident
),
def test_generator(self
):
self
.check_events(g
, [(1, 'call', g_ident
),
# call the iterator twice to generate values
# once more; returns end-of-iteration with
# actually raising an exception
def test_stop_iteration(self
):
self
.check_events(g
, [(1, 'call', g_ident
),
# call the iterator twice to generate values
# once more to hit the raise:
class ProfileSimulatorTestCase(TestCaseBase
):
return ProfileSimulator(self
)
self
.check_events(f
, [(1, 'call', f_ident
),
def test_basic_exception(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_caught_exception(self
):
self
.check_events(f
, [(1, 'call', f_ident
),
def test_distant_exception(self
):
self
.check_events(j
, [(1, 'call', j_ident
),
if hasattr(function
, "f_code"):
code
= function
.func_code
return code
.co_firstlineno
, code
.co_name
protect_ident
= ident(protect
)
def capture_events(callable, p
=None):
raise test_support
.TestFailed(
'sys.setprofile() did not raise TypeError')
sys
.setprofile(p
.callback
)
return p
.get_events()[1:-1]
def show_events(callable):
pprint
.pprint(capture_events(callable))
test_support
.run_unittest(
if __name__
== "__main__":