# HG changeset patch # User Gregory Szorc # Date 1471222272 25200 # Node ID e3501546f7e4a75892a0cbb65a0755bdb41bfccf # Parent 5d44197c208b4e26ed2fa1eb627d5dea1ee50220 profiling: add a context manager that no-ops if profiling isn't enabled And refactor dispatch.py to use it. As you can see, the resulting code is much simpler. I was tempted to inline _runcommand as part of writing this series. However, a number of extensions wrap _runcommand. So keeping it around is necessary (extensions can't easily wrap runcommand because it calls hooks before and after command execution). diff -r 5d44197c208b -r e3501546f7e4 mercurial/dispatch.py --- a/mercurial/dispatch.py Sun Aug 14 18:25:22 2016 -0700 +++ b/mercurial/dispatch.py Sun Aug 14 17:51:12 2016 -0700 @@ -898,21 +898,12 @@ repo.close() def _runcommand(ui, options, cmd, cmdfunc): - """Enables the profiler if applicable. - - ``profiling.enabled`` - boolean config that enables or disables profiling - """ - def checkargs(): + """Run a command function, possibly with profiling enabled.""" + with profiling.maybeprofile(ui): try: return cmdfunc() except error.SignatureError: - raise error.CommandError(cmd, _("invalid arguments")) - - if ui.configbool('profiling', 'enabled'): - with profiling.profile(ui): - return checkargs() - else: - return checkargs() + raise error.CommandError(cmd, _('invalid arguments')) def _exceptionwarning(ui): """Produce a warning message for the current active exception""" diff -r 5d44197c208b -r e3501546f7e4 mercurial/help/config.txt --- a/mercurial/help/config.txt Sun Aug 14 18:25:22 2016 -0700 +++ b/mercurial/help/config.txt Sun Aug 14 17:51:12 2016 -0700 @@ -1393,6 +1393,12 @@ statistical text report generated from the profiling data. The profiling is done using lsprof. +``enabled`` + Enable the profiler. + (default: false) + + This is equivalent to passing ``--profile`` on the command line. + ``type`` The type of profiler to use. (default: ls) diff -r 5d44197c208b -r e3501546f7e4 mercurial/profiling.py --- a/mercurial/profiling.py Sun Aug 14 18:25:22 2016 -0700 +++ b/mercurial/profiling.py Sun Aug 14 17:51:12 2016 -0700 @@ -143,3 +143,20 @@ val = val.replace('%', '%%') ui.log('profile', val) fp.close() + +@contextlib.contextmanager +def maybeprofile(ui): + """Profile if enabled, else do nothing. + + This context manager can be used to optionally profile if profiling + is enabled. Otherwise, it does nothing. + + The purpose of this context manager is to make calling code simpler: + just use a single code path for calling into code you may want to profile + and this function determines whether to start profiling. + """ + if ui.configbool('profiling', 'enabled'): + with profile(ui): + yield + else: + yield diff -r 5d44197c208b -r e3501546f7e4 tests/test-devel-warnings.t --- a/tests/test-devel-warnings.t Sun Aug 14 18:25:22 2016 -0700 +++ b/tests/test-devel-warnings.t Sun Aug 14 17:51:12 2016 -0700 @@ -96,7 +96,6 @@ */mercurial/dispatch.py:* in _dispatch (glob) */mercurial/dispatch.py:* in runcommand (glob) */mercurial/dispatch.py:* in _runcommand (glob) - */mercurial/dispatch.py:* in checkargs (glob) */mercurial/dispatch.py:* in (glob) */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in buggylocking (glob) @@ -132,7 +131,6 @@ */mercurial/dispatch.py:* in _dispatch (glob) */mercurial/dispatch.py:* in runcommand (glob) */mercurial/dispatch.py:* in _runcommand (glob) - */mercurial/dispatch.py:* in checkargs (glob) */mercurial/dispatch.py:* in (glob) */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in oldanddeprecated (glob) @@ -156,7 +154,6 @@ */mercurial/dispatch.py:* in _dispatch (glob) */mercurial/dispatch.py:* in runcommand (glob) */mercurial/dispatch.py:* in _runcommand (glob) - */mercurial/dispatch.py:* in checkargs (glob) */mercurial/dispatch.py:* in (glob) */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in oldanddeprecated (glob)