tests/test-ctxmanager.py
author Phil Cohen <phillco@fb.com>
Sun, 25 Jun 2017 16:56:49 -0700
changeset 33081 6582dc01aca3
parent 32279 68c43a416585
permissions -rw-r--r--
merge: pass wctx to batchremove and batchget We would like to migrate direct calls of repo.wvfs/wwrite/wread/etc to a call on the relevant workingfilectx, both as a cleanup (to reduce the number of working copy functions on `repo`), and also to facilitate an in-memory merge that doesn't write to the working copy. In order to do that, the first step is to ensure we pass the target wctx around and perform our writes and reads on it. Later, this object might become a memctx.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27703
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     1
from __future__ import absolute_import
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     2
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     3
import silenttestrunner
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     4
import unittest
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     5
28801
441491aba8c3 test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents: 27786
diff changeset
     6
from mercurial import util
27703
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     7
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     8
class contextmanager(object):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     9
    def __init__(self, name, trace):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    10
        self.name = name
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    11
        self.entered = False
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    12
        self.exited = False
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    13
        self.trace = trace
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    14
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    15
    def __enter__(self):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    16
        self.entered = True
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    17
        self.trace(('enter', self.name))
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    18
        return self
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    19
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    20
    def __exit__(self, exc_type, exc_val, exc_tb):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    21
        self.exited = exc_type, exc_val, exc_tb
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    22
        self.trace(('exit', self.name))
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    23
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    24
    def __repr__(self):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
        return '<ctx %r>' % self.name
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    26
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    27
class ctxerror(Exception):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    28
    pass
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    29
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    30
class raise_on_enter(contextmanager):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    31
    def __enter__(self):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    32
        self.trace(('raise', self.name))
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    33
        raise ctxerror(self.name)
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    34
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    35
class raise_on_exit(contextmanager):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    36
    def __exit__(self, exc_type, exc_val, exc_tb):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    37
        self.trace(('raise', self.name))
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    38
        raise ctxerror(self.name)
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    39
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    40
def ctxmgr(name, trace):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    41
    return lambda: contextmanager(name, trace)
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    42
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    43
class test_ctxmanager(unittest.TestCase):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    44
    def test_basics(self):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
        trace = []
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    46
        addtrace = trace.append
28801
441491aba8c3 test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents: 27786
diff changeset
    47
        with util.ctxmanager(ctxmgr('a', addtrace), ctxmgr('b', addtrace)) as c:
27785
ba427b51f1d8 util: rename ctxmanager's __call__ method to enter
Bryan O'Sullivan <bryano@fb.com>
parents: 27703
diff changeset
    48
            a, b = c.enter()
27703
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    49
            c.atexit(addtrace, ('atexit', 'x'))
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
            c.atexit(addtrace, ('atexit', 'y'))
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
        self.assertEqual(trace, [('enter', 'a'), ('enter', 'b'),
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    52
                                 ('atexit', 'y'), ('atexit', 'x'),
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    53
                                 ('exit', 'b'), ('exit', 'a')])
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    54
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    55
    def test_raise_on_enter(self):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
        trace = []
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    57
        addtrace = trace.append
32279
68c43a416585 tests: use context manager form of assertRaises
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28801
diff changeset
    58
        with self.assertRaises(ctxerror):
28801
441491aba8c3 test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents: 27786
diff changeset
    59
            with util.ctxmanager(ctxmgr('a', addtrace),
441491aba8c3 test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents: 27786
diff changeset
    60
                                 lambda: raise_on_enter('b', addtrace)) as c:
27785
ba427b51f1d8 util: rename ctxmanager's __call__ method to enter
Bryan O'Sullivan <bryano@fb.com>
parents: 27703
diff changeset
    61
                c.enter()
27703
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    62
                addtrace('unreachable')
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    63
        self.assertEqual(trace, [('enter', 'a'), ('raise', 'b'), ('exit', 'a')])
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    64
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    65
    def test_raise_on_exit(self):
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    66
        trace = []
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    67
        addtrace = trace.append
32279
68c43a416585 tests: use context manager form of assertRaises
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28801
diff changeset
    68
        with self.assertRaises(ctxerror):
28801
441491aba8c3 test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents: 27786
diff changeset
    69
            with util.ctxmanager(ctxmgr('a', addtrace),
441491aba8c3 test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents: 27786
diff changeset
    70
                                 lambda: raise_on_exit('b', addtrace)) as c:
27785
ba427b51f1d8 util: rename ctxmanager's __call__ method to enter
Bryan O'Sullivan <bryano@fb.com>
parents: 27703
diff changeset
    71
                c.enter()
27703
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    72
                addtrace('running')
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    73
        self.assertEqual(trace, [('enter', 'a'), ('enter', 'b'), 'running',
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    74
                                 ('raise', 'b'), ('exit', 'a')])
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    75
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    76
if __name__ == '__main__':
4e27c0a70574 util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    77
    silenttestrunner.main(__name__)