Fun with loading extensions
Greg Ward
greg at gerg.ca
Mon Jun 14 11:58:58 CDT 2010
On Mon, Jun 14, 2010 at 12:18 PM, Dirkjan Ochtman <dirkjan at ochtman.nl> wrote:
> On Mon, Jun 14, 2010 at 17:52, Greg Ward <greg at gerg.ca> wrote:
>> * dig into the closure returned by getattr(repo, name) and try to
>> figure out which extension did the wrapping (I just spent 2 minutes on
>> this and don't see an obvious way)
>> * tell the user to load this extension before the other one (not
>> very useful unless we know what the other one is)
>
> I might be stupid, but isn't this pretty much solved if we can require
> that everyone calls super() at some point?
What, even my innocent little A.py:
def reposetup(ui, repo):
def my_status(orig, *args, **kwargs):
ui.write('hello from A (wrapfunction)\n')
return orig(*args, **kwargs)
extensions.wrapfunction(repo, 'status', my_status)
? This extension is playing by the rules as they are currently
written. It doesn't make sense that it should have to do a superclass
call *in addition* to calling orig(). And besides, what is the
superclass? Does super() even work in this context? I don't see how
it can, since there is no class object handy.
But this nice innocent-looking extension breaks B, the one using the
subclass trick, if they happen to be loaded in the wrong order. I
happen to think this is B's fault for using a sneaky undocumented
trick.
The trouble is that A and B extend localrepo along two orthogonal
axes: A uses a closure and B uses a subclass. The orig() passed to
A's my_status() is repo.status *at the time A was loaded*, which means
that it's wrong if B is loaded after A.
I had to stare at extensions.wrapfunction() for several minutes before
it hit me. Try that. See if you can break the impasse. So far I
don't have a good answer, apart from "the subclass trick is evil:
don't use it".
Greg
More information about the Mercurial-devel
mailing list