Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a9f0687

Browse files
committed
Fix a bug in nested() - if one of the sub-context-managers swallows the
exception, it should not be propagated up. With unit tests.
1 parent 6db0e00 commit a9f0687

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

Lib/contextlib.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ def nested(*contexts):
9191
"""
9292
exits = []
9393
vars = []
94-
exc = (None, None, None)
9594
try:
9695
try:
9796
for context in contexts:
@@ -103,13 +102,17 @@ def nested(*contexts):
103102
yield vars
104103
except:
105104
exc = sys.exc_info()
105+
else:
106+
exc = (None, None, None)
106107
finally:
107108
while exits:
108109
exit = exits.pop()
109110
try:
110111
exit(*exc)
111112
except:
112113
exc = sys.exc_info()
114+
else:
115+
exc = (None, None, None)
113116
if exc != (None, None, None):
114117
raise
115118

Lib/test/test_contextlib.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,60 @@ def b():
107107
else:
108108
self.fail("Didn't raise ZeroDivisionError")
109109

110+
def test_nested_b_swallows(self):
111+
@contextmanager
112+
def a():
113+
yield
114+
@contextmanager
115+
def b():
116+
try:
117+
yield
118+
except:
119+
# Swallow the exception
120+
pass
121+
try:
122+
with nested(a(), b()):
123+
1/0
124+
except ZeroDivisionError:
125+
self.fail("Didn't swallow ZeroDivisionError")
126+
127+
def test_nested_break(self):
128+
@contextmanager
129+
def a():
130+
yield
131+
state = 0
132+
while True:
133+
state += 1
134+
with nested(a(), a()):
135+
break
136+
state += 10
137+
self.assertEqual(state, 1)
138+
139+
def test_nested_continue(self):
140+
@contextmanager
141+
def a():
142+
yield
143+
state = 0
144+
while state < 3:
145+
state += 1
146+
with nested(a(), a()):
147+
continue
148+
state += 10
149+
self.assertEqual(state, 3)
150+
151+
def test_nested_return(self):
152+
@contextmanager
153+
def a():
154+
try:
155+
yield
156+
except:
157+
pass
158+
def foo():
159+
with nested(a(), a()):
160+
return 1
161+
return 10
162+
self.assertEqual(foo(), 1)
163+
110164
class ClosingTestCase(unittest.TestCase):
111165

112166
# XXX This needs more work

0 commit comments

Comments
 (0)