##// END OF EJS Templates
Fix for nested()
Thomas Kluyver -
Show More
@@ -1,48 +1,50 b''
1 """Backwards compatibility - we use contextlib.nested to support Python 2.6,
1 """Backwards compatibility - we use contextlib.nested to support Python 2.6,
2 but it's removed in Python 3.2."""
2 but it's removed in Python 3.2."""
3
3
4 # TODO : Remove this once we drop support for Python 2.6, and use
4 # TODO : Remove this once we drop support for Python 2.6, and use
5 # "with a, b:" instead.
5 # "with a, b:" instead.
6
6
7 import sys
8
7 from contextlib import contextmanager
9 from contextlib import contextmanager
8
10
9 @contextmanager
11 @contextmanager
10 def nested(*managers):
12 def nested(*managers):
11 """Combine multiple context managers into a single nested context manager.
13 """Combine multiple context managers into a single nested context manager.
12
14
13 This function has been deprecated in favour of the multiple manager form
15 This function has been deprecated in favour of the multiple manager form
14 of the with statement.
16 of the with statement.
15
17
16 The one advantage of this function over the multiple manager form of the
18 The one advantage of this function over the multiple manager form of the
17 with statement is that argument unpacking allows it to be
19 with statement is that argument unpacking allows it to be
18 used with a variable number of context managers as follows:
20 used with a variable number of context managers as follows:
19
21
20 with nested(*managers):
22 with nested(*managers):
21 do_something()
23 do_something()
22
24
23 """
25 """
24 exits = []
26 exits = []
25 vars = []
27 vars = []
26 exc = (None, None, None)
28 exc = (None, None, None)
27 try:
29 try:
28 for mgr in managers:
30 for mgr in managers:
29 exit = mgr.__exit__
31 exit = mgr.__exit__
30 enter = mgr.__enter__
32 enter = mgr.__enter__
31 vars.append(enter())
33 vars.append(enter())
32 exits.append(exit)
34 exits.append(exit)
33 yield vars
35 yield vars
34 except:
36 except:
35 exc = sys.exc_info()
37 exc = sys.exc_info()
36 finally:
38 finally:
37 while exits:
39 while exits:
38 exit = exits.pop()
40 exit = exits.pop()
39 try:
41 try:
40 if exit(*exc):
42 if exit(*exc):
41 exc = (None, None, None)
43 exc = (None, None, None)
42 except:
44 except:
43 exc = sys.exc_info()
45 exc = sys.exc_info()
44 if exc != (None, None, None):
46 if exc != (None, None, None):
45 # Don't rely on sys.exc_info() still containing
47 # Don't rely on sys.exc_info() still containing
46 # the right information. Another exception may
48 # the right information. Another exception may
47 # have been raised and caught by an exit method
49 # have been raised and caught by an exit method
48 raise exc[0], exc[1], exc[2]
50 raise exc[0], exc[1], exc[2]
General Comments 0
You need to be logged in to leave comments. Login now