author | Jun Wu <quark@fb.com> |
Wed, 04 May 2016 18:18:24 +0100 | |
changeset 29070 | 29a7d591ff42 |
parent 28801 | 441491aba8c3 |
child 32279 | 68c43a416585 |
permissions | -rw-r--r-- |
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 |
27786
4a7dc29bfad8
test-ctxmanager: fix Python 2.6 compatibility problem
Bryan O'Sullivan <bryano@fb.com>
parents:
27785
diff
changeset
|
58 |
def go(): |
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') |
27786
4a7dc29bfad8
test-ctxmanager: fix Python 2.6 compatibility problem
Bryan O'Sullivan <bryano@fb.com>
parents:
27785
diff
changeset
|
63 |
self.assertRaises(ctxerror, go) |
27703
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
64 |
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
|
65 |
|
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
66 |
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
|
67 |
trace = [] |
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
68 |
addtrace = trace.append |
27786
4a7dc29bfad8
test-ctxmanager: fix Python 2.6 compatibility problem
Bryan O'Sullivan <bryano@fb.com>
parents:
27785
diff
changeset
|
69 |
def go(): |
28801
441491aba8c3
test-ctxmanager: stop direct symbol import of mercurial.util
Yuya Nishihara <yuya@tcha.org>
parents:
27786
diff
changeset
|
70 |
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
|
71 |
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
|
72 |
c.enter() |
27703
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
73 |
addtrace('running') |
27786
4a7dc29bfad8
test-ctxmanager: fix Python 2.6 compatibility problem
Bryan O'Sullivan <bryano@fb.com>
parents:
27785
diff
changeset
|
74 |
self.assertRaises(ctxerror, go) |
27703
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
75 |
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
|
76 |
('raise', 'b'), ('exit', 'a')]) |
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
77 |
|
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
78 |
if __name__ == '__main__': |
4e27c0a70574
util: introduce ctxmanager, to avoid nested try/finally blocks
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff
changeset
|
79 |
silenttestrunner.main(__name__) |