# HG changeset patch # User Greg Ward # Date 2010-06-15 17:04:22 # Node ID 367ce8514da08c4117bfeaea98946c2463bf743a # Parent 3bc892f740d610ea9faac4b42e7eb80c7cc5ae11 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. diff --git a/mercurial/extensions.py b/mercurial/extensions.py --- a/mercurial/extensions.py +++ b/mercurial/extensions.py @@ -124,6 +124,38 @@ def wrapcommand(table, command, wrapper) 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)