Patchwork extensions: extract partial application into a bind() function

login
register
mail settings
Submitter Eric Sumner
Date April 15, 2015, 4:28 p.m.
Message ID <a8fd41a5a5c1568efa8c.1429115281@waste.org>
Download mbox | patch
Permalink /patch/8680/
State Superseded
Headers show

Comments

Eric Sumner - April 15, 2015, 4:28 p.m.
# HG changeset patch
# User Eric Sumner <ericsumner@fb.com>
# Date 1429114685 14400
#      Wed Apr 15 12:18:05 2015 -0400
# Node ID a8fd41a5a5c1568efa8c1de185a888d6c558f067
# Parent  c560d8c687916cb70a6d54c2c9ddcb5c9e457be2
extensions: extract partial application into a bind() function

We use partial function application for wrapping existing Mercurial functions,
and it's implemented separately each time.  This patch extracts the partial
application into a new bind() function that can be used on its own by extensions
when appropriate.

In particular, the evolve extension needs to wrap functions in the various
bundle2 processing dictionaries, which the pre-existing methods don't support.

Patch

diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -152,6 +152,18 @@ 
     else:
         _aftercallbacks.setdefault(extension, []).append(callback)
 
+def bind(func, *args):
+    '''Partial function application
+
+      Returns a new function that is the partial application of args and kwargs
+      to func.  For example,
+      
+          f(1, 2, bar=3) === bind(f, 1)(2, bar=3)'''
+    assert callable(func)
+    def closure(*a, **kw):
+        return func(*(args + a), **kw)
+    return closure
+
 def wrapcommand(table, command, wrapper, synopsis=None, docstring=None):
     '''Wrap the command named `command' in table
 
@@ -189,9 +201,7 @@ 
             break
 
     origfn = entry[0]
-    def wrap(*args, **kwargs):
-        return util.checksignature(wrapper)(
-            util.checksignature(origfn), *args, **kwargs)
+    wrap = bind(util.checksignature(wrapper), util.checksignature(origfn))
 
     wrap.__module__ = getattr(origfn, '__module__')
 
@@ -241,12 +251,10 @@ 
     subclass trick.
     '''
     assert callable(wrapper)
-    def wrap(*args, **kwargs):
-        return wrapper(origfn, *args, **kwargs)
 
     origfn = getattr(container, funcname)
     assert callable(origfn)
-    setattr(container, funcname, wrap)
+    setattr(container, funcname, bind(wrapper, origfn))
     return origfn
 
 def _disabledpaths(strip_init=False):