mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 16:31:02 +03:00
c363f01ef4
Before this patch, we don't have a safe way to undo a wrapfunction because other extensions may wrap the same function and calling setattr will undo them accidentally. This patch adds an "unwrapfunction" to address the issue. It removes the wrapper from the wrapper chain, and re-wraps everything, which is not the most efficient but short and easy to understand. We can revisit the code if we have perf issues with long chains. The "undo" feature is useful in cases like wrapping a function just in a scope. Like, having a "select" command to interactively (using arrow keys) select content from some output (ex. smartlog). It could wrap "ui.label" to extract interesting texts just in the "select" command.
40 lines
1.0 KiB
Python
40 lines
1.0 KiB
Python
from __future__ import absolute_import, print_function
|
|
|
|
from mercurial import extensions
|
|
|
|
def genwrapper(x):
|
|
def f(orig, *args, **kwds):
|
|
return [x] + orig(*args, **kwds)
|
|
f.x = x
|
|
return f
|
|
|
|
def getid(wrapper):
|
|
return getattr(wrapper, 'x', '-')
|
|
|
|
wrappers = [genwrapper(i) for i in range(5)]
|
|
|
|
class dummyclass(object):
|
|
def getstack(self):
|
|
return ['orig']
|
|
|
|
dummy = dummyclass()
|
|
|
|
def batchwrap(wrappers):
|
|
for w in wrappers:
|
|
extensions.wrapfunction(dummy, 'getstack', w)
|
|
print('wrap %d: %s' % (getid(w), dummy.getstack()))
|
|
|
|
def batchunwrap(wrappers):
|
|
for w in wrappers:
|
|
result = None
|
|
try:
|
|
result = extensions.unwrapfunction(dummy, 'getstack', w)
|
|
msg = str(dummy.getstack())
|
|
except (ValueError, IndexError) as e:
|
|
msg = e.__class__.__name__
|
|
print('unwrap %s: %s: %s' % (getid(w), getid(result), msg))
|
|
|
|
batchwrap(wrappers + [wrappers[0]])
|
|
batchunwrap([(wrappers[i] if i >= 0 else None)
|
|
for i in [3, None, 0, 4, 0, 2, 1, None]])
|