[PATCH 3 of 3] extensions: add unwrapfunction to undo wrapfunction

Martijn Pieters mj at zopatista.com
Fri Jul 1 10:02:14 EDT 2016


On 1 July 2016 at 14:27, Jun Wu <quark at fb.com> wrote:
> Yes the current code is not optimized for performance (as mentioned in
> commit message). The optimized code would be re-inventing getwrapperchain
> and I want to avoid duplication. getwrapperchain is exposed as an API
> because I plan to have something like "debugwraps" to visualize the wrapped
> functions in the future.
>
>> You could just use a stack of functions to rewrap; this avoids having
>> to re-do the whole chain:
>>
>>     chain = getwrapperchain(container, funcname)[::-1]
>>     rewrap = []
>>     while chain:
>>         wrapper = chain.pop()
>>         if wrapper == origfn:
>>             break
>>         rewrap.append(wrapper)
>>     if chain:
>>         # we found the original and removed it; rewrap whatever we had to remove
>>                  # to find it.
>>         setattr(container, funcname, chain[-1])
>>         while rewrap:
>>             wrapfunction(container, funcname, rewrap.pop())
>
> I don't think this works. There are two different wrappers:
>
>   1. the one you passed to wrapfunction, say it's "f"
>   2. f.bind(origfunc), say it's "g"
>
> getwrapperchain returns "f"s to make them comparable and hides "g"s for
> simplicity. We need to setattr to a "g".

Ah, yes, you are correct. I had the wrong mental model (decorators),
while the actual attribute on the container is a chain of closures
really.

This also invalidates my __wrapper__ argument on the other patch.

-- 
Martijn Pieters


More information about the Mercurial-devel mailing list