extensions: recommend against using wrapfunction for repo methods
authorGreg Ward <greg-hg@gerg.ca>
Tue, 15 Jun 2010 13:04:22 -0400
changeset 11402 367ce8514da0
parent 11401 3bc892f740d6
child 11403 f7d7de6eccc8
extensions: recommend against using wrapfunction for repo methods Instead, all extensions should use the "dynamic subclass" trick: subclass repo.__class__ and then replace repo.__class__ with your new subclass. This avoids conflicts that happen when one extension uses wrapfunction and another uses subclassing to extend the same method of localrepository.
mercurial/extensions.py
--- a/mercurial/extensions.py	Sat Jun 19 17:19:15 2010 +0200
+++ b/mercurial/extensions.py	Tue Jun 15 13:04:22 2010 -0400
@@ -124,6 +124,38 @@
     return entry
 
 def wrapfunction(container, funcname, wrapper):
+    '''Wrap the function named funcname in container
+
+    It is replacing with your wrapper. The container is typically a
+    module, class, or instance.
+
+    The wrapper will be called like
+
+      wrapper(orig, *args, **kwargs)
+
+    where orig is the original (wrapped) function, and *args, **kwargs
+    are the arguments passed to it.
+
+    Wrapping methods of the repository object is not recommended since
+    it conflicts with extensions that extend the repository by
+    subclassing. All extensions that need to extend methods of
+    localrepository should use this subclassing trick: namely,
+    reposetup() should look like
+
+      def reposetup(ui, repo):
+          class myrepo(repo.__class__):
+              def whatever(self, *args, **kwargs):
+                  [...extension stuff...]
+                  super(myrepo, self).whatever(*args, **kwargs)
+                  [...extension stuff...]
+
+          repo.__class__ = myrepo
+
+    In general, combining wrapfunction() with subclassing does not
+    work. Since you cannot control what other extensions are loaded by
+    your end users, you should play nicely with others by using the
+    subclass trick.
+    '''
     def wrap(*args, **kwargs):
         return wrapper(origfn, *args, **kwargs)