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).
--- 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"""
--- 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)
--- 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
--- 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 <lambda> (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 <lambda> (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 <lambda> (glob)
*/mercurial/util.py:* in check (glob)
$TESTTMP/buggylocking.py:* in oldanddeprecated (glob)