tests/test-extensions-wrapfunction.py
author Matt Harbison <matt_harbison@yahoo.com>
Mon, 20 Aug 2018 16:19:36 -0400
changeset 39224 5e52b6da9c0c
parent 37938 ac865f020b99
child 43076 2372284d9457
permissions -rw-r--r--
tests: demonstrate a problem with renames on the p2 side of a conversion I think this is related to the octopus merge being sloppy, and that's having a cascading affect on the fixup merge. If this change is made on p1 (specifically with the 'Added parent file' commit), the failure doesn't occur. The file modification with the rename doesn't seem to be necessary, but it's what's happening in a production repo where I first noticed, so I left it. This is an example of the manifest divergence I'd been seeing, which wasn't fixed by Yuya's recent changes. This is separate from the changelog divergence I was also seeing[1]. Probably nobody cares about bzr anymore, but this will also affect git, since the octopus fixup code is in the hg sink. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2018-August/120473.html

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 is not None and i >= 0 else None)
             for i in [3, None, 0, 4, 0, 2, 1, None]])

wrap0 = extensions.wrappedfunction(dummy, 'getstack', wrappers[0])
wrap1 = extensions.wrappedfunction(dummy, 'getstack', wrappers[1])

# Use them in a different order from how they were created to check that
# the wrapping happens in __enter__, not in __init__
print('context manager', dummy.getstack())
with wrap1:
    print('context manager', dummy.getstack())
    with wrap0:
        print('context manager', dummy.getstack())
        # Bad programmer forgets to unwrap the function, but the context
        # managers still unwrap their wrappings.
        extensions.wrapfunction(dummy, 'getstack', wrappers[2])
        print('context manager', dummy.getstack())
    print('context manager', dummy.getstack())
print('context manager', dummy.getstack())

# Wrap callable object which has no __name__
class callableobj(object):
    def __call__(self):
        return ['orig']
dummy.cobj = callableobj()
extensions.wrapfunction(dummy, 'cobj', wrappers[0])
print('wrap callable object', dummy.cobj())