Rev 4085: Refactor profiling exception handling to restore clear layers - command handling in commands.py, profiling in lsprof.py. in http://people.ubuntu.com/~robertc/baz2.0/pending/lsprof
Robert Collins
robertc at robertcollins.net
Sun Mar 8 06:18:09 GMT 2009
At http://people.ubuntu.com/~robertc/baz2.0/pending/lsprof
------------------------------------------------------------
revno: 4085
revision-id: robertc at robertcollins.net-20090308061806-uvu37ccjrrzuspei
parent: pqm at pqm.ubuntu.com-20090306030219-enauehb3achqqq7c
committer: Robert Collins <robertc at robertcollins.net>
branch nick: lsprof
timestamp: Sun 2009-03-08 17:18:06 +1100
message:
Refactor profiling exception handling to restore clear layers - command handling in commands.py, profiling in lsprof.py.
=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py 2009-02-23 15:42:47 +0000
+++ b/bzrlib/commands.py 2009-03-08 06:18:06 +0000
@@ -672,12 +672,13 @@
tracer = trace.Trace(count=1, trace=0)
sys.settrace(tracer.globaltrace)
- ret = the_callable(*args, **kwargs)
-
- sys.settrace(None)
- results = tracer.results()
- results.write_results(show_missing=1, summary=False,
- coverdir=dirname)
+ try:
+ return exception_to_return_code(the_callable, *args, **kwargs)
+ finally:
+ sys.settrace(None)
+ results = tracer.results()
+ results.write_results(show_missing=1, summary=False,
+ coverdir=dirname)
def apply_profiled(the_callable, *args, **kwargs):
@@ -688,7 +689,8 @@
try:
prof = hotshot.Profile(pfname)
try:
- ret = prof.runcall(the_callable, *args, **kwargs) or 0
+ ret = prof.runcall(exception_to_return_code, the_callable, *args,
+ **kwargs) or 0
finally:
prof.close()
stats = hotshot.stats.load(pfname)
@@ -703,9 +705,50 @@
os.remove(pfname)
+def exception_to_return_code(the_callable, *args, **kwargs):
+ """UI level helper for profiling and coverage.
+
+ This transforms exceptions into a return value of 3. As such its only
+ relevant to the UI layer, and should never be called where catching
+ exceptions may be desirable.
+ """
+ try:
+ return the_callable(*args, **kwargs)
+ except (KeyboardInterrupt, Exception), e:
+ # used to handle AssertionError and KeyboardInterrupt
+ # specially here, but hopefully they're handled ok by the logger now
+ exc_info = sys.exc_info()
+ exitcode = trace.report_exception(exc_info, sys.stderr)
+ if os.environ.get('BZR_PDB'):
+ print '**** entering debugger'
+ tb = exc_info[2]
+ import pdb
+ if sys.version_info[:2] < (2, 6):
+ # XXX: we want to do
+ # pdb.post_mortem(tb)
+ # but because pdb.post_mortem gives bad results for tracebacks
+ # from inside generators, we do it manually.
+ # (http://bugs.python.org/issue4150, fixed in Python 2.6)
+
+ # Setup pdb on the traceback
+ p = pdb.Pdb()
+ p.reset()
+ p.setup(tb.tb_frame, tb)
+ # Point the debugger at the deepest frame of the stack
+ p.curindex = len(p.stack) - 1
+ p.curframe = p.stack[p.curindex]
+ # Start the pdb prompt.
+ p.print_stack_entry(p.stack[p.curindex])
+ p.execRcLines()
+ p.cmdloop()
+ else:
+ pdb.post_mortem(tb)
+ return exitcode
+
+
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
from bzrlib.lsprof import profile
- ret, stats = profile(the_callable, *args, **kwargs)
+ ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
stats.sort()
if filename is None:
stats.pprint()
@@ -915,40 +958,12 @@
def run_bzr_catch_errors(argv):
- # Note: The except clause logic below should be kept in sync with the
- # profile() routine in lsprof.py.
- try:
- return run_bzr(argv)
- except (KeyboardInterrupt, Exception), e:
- # used to handle AssertionError and KeyboardInterrupt
- # specially here, but hopefully they're handled ok by the logger now
- exc_info = sys.exc_info()
- exitcode = trace.report_exception(exc_info, sys.stderr)
- if os.environ.get('BZR_PDB'):
- print '**** entering debugger'
- tb = exc_info[2]
- import pdb
- if sys.version_info[:2] < (2, 6):
- # XXX: we want to do
- # pdb.post_mortem(tb)
- # but because pdb.post_mortem gives bad results for tracebacks
- # from inside generators, we do it manually.
- # (http://bugs.python.org/issue4150, fixed in Python 2.6)
-
- # Setup pdb on the traceback
- p = pdb.Pdb()
- p.reset()
- p.setup(tb.tb_frame, tb)
- # Point the debugger at the deepest frame of the stack
- p.curindex = len(p.stack) - 1
- p.curframe = p.stack[p.curindex]
- # Start the pdb prompt.
- p.print_stack_entry(p.stack[p.curindex])
- p.execRcLines()
- p.cmdloop()
- else:
- pdb.post_mortem(tb)
- return exitcode
+ """Run a bzr command with parameters as described by argv.
+
+ This function assumed that that UI layer is setup, that symbol deprecations
+ are already applied, and that unicode decoding has already been performed on argv.
+ """
+ return exception_to_return_code(run_bzr, argv)
def run_bzr_catch_user_errors(argv):
=== modified file 'bzrlib/lsprof.py'
--- a/bzrlib/lsprof.py 2009-01-17 01:30:58 +0000
+++ b/bzrlib/lsprof.py 2009-03-08 06:18:06 +0000
@@ -29,23 +29,18 @@
def profile(f, *args, **kwds):
"""Run a function profile.
+ Exceptions are not caught: If you need stats even when exceptions are to be
+ raised, passing in a closure that will catch the exceptions and transform
+ them appropriately for your driver function.
+
:return: The functions return value and a stats object.
"""
global _g_threadmap
p = Profiler()
p.enable(subcalls=True)
threading.setprofile(_thread_profile)
- # Note: The except clause is needed below so that profiling data still
- # gets dumped even when exceptions are encountered. The except clause code
- # is taken straight from run_bzr_catch_errrors() in commands.py and ought
- # to be kept in sync with it.
try:
- try:
- ret = f(*args, **kwds)
- except (KeyboardInterrupt, Exception), e:
- import bzrlib.trace
- bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
- ret = 3
+ ret = f(*args, **kwds)
finally:
p.disable()
for pp in _g_threadmap.values():
More information about the bazaar-commits
mailing list