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