[PATCH 2 of 4] extensions: introduce a class interposition function
Bryan O'Sullivan
bos at serpentine.com
Mon Jun 25 16:58:32 CDT 2012
# HG changeset patch
# User Bryan O'Sullivan <bryano at fb.com>
# Date 1340657771 25200
# Node ID e5a5191a08b8077e4d05e7bf32552cf382db07dd
# Parent 5c2fe39e4efcc5c70797afe149054a38855e7516
extensions: introduce a class interposition function
This allows an existing class to be augmented in a transparent way,
without its subclasses or callers needing to participate.
diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -188,6 +188,34 @@ def wrapfunction(container, funcname, wr
setattr(container, funcname, wrap)
return origfn
+def replaceclass(container, classname):
+ '''Replace a class with another in a module, and interpose it into
+ the hierarchies of all loaded subclasses. This function is
+ intended for use as a decorator.
+
+ import mymodule
+ @replaceclass(mymodule, 'myclass')
+ class mysubclass(mymodule.myclass):
+ def foo(self):
+ f = super(mysubclass, self).foo()
+ return f + ' bar'
+
+ Existing instances of the class being replaced will not have their
+ __class__ modified, so call this function before creating any
+ objects of the target type.
+ '''
+ def wrap(cls):
+ oldcls = getattr(container, classname)
+ oldbases = (oldcls,)
+ newbases = (cls,)
+ for subcls in oldcls.__subclasses__():
+ if subcls is not cls:
+ assert subcls.__bases__ == oldbases
+ subcls.__bases__ = newbases
+ setattr(container, classname, cls)
+ return cls
+ return wrap
+
def _disabledpaths(strip_init=False):
'''find paths of disabled extensions. returns a dict of {name: path}
removes /__init__.py from packages if strip_init is True'''
More information about the Mercurial-devel
mailing list