D632: wrapfunction: use functools.partial if possible

quark (Jun Wu) phabricator at mercurial-scm.org
Tue Sep 5 23:48:27 UTC 2017


quark created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Every `extensions.bind` call inserts a frame in traceback:
  
    ... in closure
      return func(*(args + a), **kw)
  
  which makes traceback noisy.
  
  The Python stdlib has a `functools.partial` which is backed by C code and
  not pollute traceback. However it has 2 issues:
  
  1. Does not work with instancemethod.
  2. Having a field `args`, which conflicts with alias internal code.
  
  This patch makes `wrapfunction` use `functools.partial` if it's not an
  instandmethod, and renames `args` so alias code works fine.
  
  As an example, `hg rebase -s . -d . --traceback` got 6 lines removed in my
  setup:
  
     Traceback (most recent call last):
       File "hg/mercurial/scmutil.py", line 150, in callcatch
         return func()
       File "hg/mercurial/dispatch.py", line 293, in _runcatchfunc
         return _dispatch(req)
       File "hg/mercurial/dispatch.py", line 898, in _dispatch
         cmdpats, cmdoptions)
    -  File "hg/mercurial/extensions.py", line 333, in closure
    -    return func(*(args + a), **kw)
       File "hg/hgext/journal.py", line 84, in runcommand
         return orig(lui, repo, cmd, fullargs, *args)
    -  File "hg/mercurial/extensions.py", line 333, in closure
    -    return func(*(args + a), **kw)
       File "fb-hgext/hgext3rd/fbamend/hiddenoverride.py", line 119, in runcommand
         result = orig(lui, repo, cmd, fullargs, *args)
       File "hg/mercurial/dispatch.py", line 660, in runcommand
         ret = _runcommand(ui, options, cmd, d)
    -  File "hg/mercurial/extensions.py", line 333, in closure
    -    return func(*(args + a), **kw)
       File "hg/hgext/pager.py", line 69, in pagecmd
         return orig(ui, options, cmd, cmdfunc)
       File "hg/mercurial/dispatch.py", line 906, in _runcommand
         return cmdfunc()
       File "hg/mercurial/dispatch.py", line 895, in <lambda>
         d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
      ....

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D632

AFFECTED FILES
  mercurial/dispatch.py
  mercurial/extensions.py

CHANGE DETAILS

diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 
+import functools
 import imp
 import inspect
 import os
@@ -332,6 +333,7 @@
 
 def _updatewrapper(wrap, origfn, unboundwrapper):
     '''Copy and add some useful attributes to wrapper'''
+    wrap.__name__ = origfn.__name__
     wrap.__module__ = getattr(origfn, '__module__')
     wrap.__doc__ = getattr(origfn, '__doc__')
     wrap.__dict__.update(getattr(origfn, '__dict__', {}))
@@ -459,7 +461,14 @@
 
     origfn = getattr(container, funcname)
     assert callable(origfn)
-    wrap = bind(wrapper, origfn)
+    if util.safehasattr(origfn, 'im_self'):
+        # traditional bind, work with bound and unbound instancemethod, but
+        # will insert a frame in traceback output
+        wrap = bind(wrapper, origfn)
+    else:
+        # functools.partial, does not work with instancemethod, but won't
+        # insert a frame in traceback output
+        wrap = functools.partial(wrapper, origfn)
     _updatewrapper(wrap, origfn, wrapper)
     setattr(container, funcname, wrap)
     return origfn
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -357,7 +357,10 @@
     return -1
 
 def aliasargs(fn, givenargs):
-    args = getattr(fn, 'args', [])
+    args = []
+    # only care about alias 'args', ignore 'args' set by extensions.wrapfunction
+    if not util.safehasattr(fn, '_origfunc'):
+        args = getattr(fn, 'args', args)
     if args:
         cmd = ' '.join(map(util.shellquote, args))
 



To: quark, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list