blob: 42b90b612de0e07aaa14a27cf1782b87ff91ee1e [file] [log] [blame]
Guido van Rossum1a5e21e2006-02-28 21:57:43 +00001"""Unit tests for contextlib.py, and other context managers."""
2
R. David Murrayf28fd242010-02-23 00:24:49 +00003import sys
Guido van Rossum1a5e21e2006-02-28 21:57:43 +00004import tempfile
5import unittest
6import threading
7from contextlib import * # Tests __all__
Collin Winterc2898c52007-04-25 17:29:52 +00008from test import test_support
Florent Xicluna6257a7b2010-03-31 22:01:03 +00009
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000010
11class ContextManagerTestCase(unittest.TestCase):
12
Nick Coghlanafd5e632006-05-03 13:02:47 +000013 def test_contextmanager_plain(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000014 state = []
Nick Coghlanafd5e632006-05-03 13:02:47 +000015 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000016 def woohoo():
17 state.append(1)
18 yield 42
19 state.append(999)
20 with woohoo() as x:
21 self.assertEqual(state, [1])
22 self.assertEqual(x, 42)
23 state.append(x)
24 self.assertEqual(state, [1, 42, 999])
25
Nick Coghlanafd5e632006-05-03 13:02:47 +000026 def test_contextmanager_finally(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000027 state = []
Nick Coghlanafd5e632006-05-03 13:02:47 +000028 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000029 def woohoo():
30 state.append(1)
31 try:
32 yield 42
33 finally:
34 state.append(999)
Florent Xicluna6257a7b2010-03-31 22:01:03 +000035 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000036 with woohoo() as x:
37 self.assertEqual(state, [1])
38 self.assertEqual(x, 42)
39 state.append(x)
40 raise ZeroDivisionError()
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000041 self.assertEqual(state, [1, 42, 999])
42
Nick Coghlanafd5e632006-05-03 13:02:47 +000043 def test_contextmanager_no_reraise(self):
44 @contextmanager
Phillip J. Eby6edd2582006-03-25 00:28:24 +000045 def whee():
46 yield
Guido van Rossumda5b7012006-05-02 19:47:52 +000047 ctx = whee()
Phillip J. Eby6edd2582006-03-25 00:28:24 +000048 ctx.__enter__()
49 # Calling __exit__ should not result in an exception
Benjamin Peterson5c8da862009-06-30 22:57:08 +000050 self.assertFalse(ctx.__exit__(TypeError, TypeError("foo"), None))
Phillip J. Eby6edd2582006-03-25 00:28:24 +000051
Nick Coghlanafd5e632006-05-03 13:02:47 +000052 def test_contextmanager_trap_yield_after_throw(self):
53 @contextmanager
Phillip J. Eby6edd2582006-03-25 00:28:24 +000054 def whoo():
55 try:
56 yield
57 except:
58 yield
Guido van Rossumda5b7012006-05-02 19:47:52 +000059 ctx = whoo()
Phillip J. Eby6edd2582006-03-25 00:28:24 +000060 ctx.__enter__()
61 self.assertRaises(
62 RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None
63 )
64
Nick Coghlanafd5e632006-05-03 13:02:47 +000065 def test_contextmanager_except(self):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000066 state = []
Nick Coghlanafd5e632006-05-03 13:02:47 +000067 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000068 def woohoo():
69 state.append(1)
70 try:
71 yield 42
72 except ZeroDivisionError, e:
73 state.append(e.args[0])
74 self.assertEqual(state, [1, 42, 999])
75 with woohoo() as x:
76 self.assertEqual(state, [1])
77 self.assertEqual(x, 42)
78 state.append(x)
79 raise ZeroDivisionError(999)
80 self.assertEqual(state, [1, 42, 999])
81
R. David Murrayf28fd242010-02-23 00:24:49 +000082 def _create_contextmanager_attribs(self):
Phillip J. Eby35fd1422006-03-28 00:07:24 +000083 def attribs(**kw):
84 def decorate(func):
85 for k,v in kw.items():
86 setattr(func,k,v)
87 return func
88 return decorate
Nick Coghlanafd5e632006-05-03 13:02:47 +000089 @contextmanager
Phillip J. Eby35fd1422006-03-28 00:07:24 +000090 @attribs(foo='bar')
91 def baz(spam):
92 """Whee!"""
R. David Murrayf28fd242010-02-23 00:24:49 +000093 return baz
94
95 def test_contextmanager_attribs(self):
96 baz = self._create_contextmanager_attribs()
Phillip J. Eby35fd1422006-03-28 00:07:24 +000097 self.assertEqual(baz.__name__,'baz')
98 self.assertEqual(baz.foo, 'bar')
R. David Murrayf28fd242010-02-23 00:24:49 +000099
100 @unittest.skipIf(sys.flags.optimize >= 2,
101 "Docstrings are omitted with -O2 and above")
102 def test_contextmanager_doc_attrib(self):
103 baz = self._create_contextmanager_attribs()
Phillip J. Eby35fd1422006-03-28 00:07:24 +0000104 self.assertEqual(baz.__doc__, "Whee!")
105
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000106class NestedTestCase(unittest.TestCase):
107
108 # XXX This needs more work
109
110 def test_nested(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000111 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000112 def a():
113 yield 1
Nick Coghlanafd5e632006-05-03 13:02:47 +0000114 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000115 def b():
116 yield 2
Nick Coghlanafd5e632006-05-03 13:02:47 +0000117 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000118 def c():
119 yield 3
120 with nested(a(), b(), c()) as (x, y, z):
121 self.assertEqual(x, 1)
122 self.assertEqual(y, 2)
123 self.assertEqual(z, 3)
124
125 def test_nested_cleanup(self):
126 state = []
Nick Coghlanafd5e632006-05-03 13:02:47 +0000127 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000128 def a():
129 state.append(1)
130 try:
131 yield 2
132 finally:
133 state.append(3)
Nick Coghlanafd5e632006-05-03 13:02:47 +0000134 @contextmanager
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000135 def b():
136 state.append(4)
137 try:
138 yield 5
139 finally:
140 state.append(6)
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000141 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000142 with nested(a(), b()) as (x, y):
143 state.append(x)
144 state.append(y)
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000145 1 // 0
146 self.assertEqual(state, [1, 4, 2, 5, 6, 3])
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000147
Nick Coghlanda2268f2006-04-24 04:37:15 +0000148 def test_nested_right_exception(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000149 @contextmanager
Nick Coghlanda2268f2006-04-24 04:37:15 +0000150 def a():
151 yield 1
152 class b(object):
153 def __enter__(self):
154 return 2
155 def __exit__(self, *exc_info):
156 try:
157 raise Exception()
158 except:
159 pass
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000160 with self.assertRaises(ZeroDivisionError):
Nick Coghlanda2268f2006-04-24 04:37:15 +0000161 with nested(a(), b()) as (x, y):
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000162 1 // 0
163 self.assertEqual((x, y), (1, 2))
Nick Coghlanda2268f2006-04-24 04:37:15 +0000164
Guido van Rossuma9f06872006-03-01 17:10:01 +0000165 def test_nested_b_swallows(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000166 @contextmanager
Guido van Rossuma9f06872006-03-01 17:10:01 +0000167 def a():
168 yield
Nick Coghlanafd5e632006-05-03 13:02:47 +0000169 @contextmanager
Guido van Rossuma9f06872006-03-01 17:10:01 +0000170 def b():
171 try:
172 yield
173 except:
174 # Swallow the exception
175 pass
176 try:
177 with nested(a(), b()):
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000178 1 // 0
Guido van Rossuma9f06872006-03-01 17:10:01 +0000179 except ZeroDivisionError:
180 self.fail("Didn't swallow ZeroDivisionError")
181
182 def test_nested_break(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000183 @contextmanager
Guido van Rossuma9f06872006-03-01 17:10:01 +0000184 def a():
185 yield
186 state = 0
187 while True:
188 state += 1
189 with nested(a(), a()):
190 break
191 state += 10
192 self.assertEqual(state, 1)
193
194 def test_nested_continue(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000195 @contextmanager
Guido van Rossuma9f06872006-03-01 17:10:01 +0000196 def a():
197 yield
198 state = 0
199 while state < 3:
200 state += 1
201 with nested(a(), a()):
202 continue
203 state += 10
204 self.assertEqual(state, 3)
205
206 def test_nested_return(self):
Nick Coghlanafd5e632006-05-03 13:02:47 +0000207 @contextmanager
Guido van Rossuma9f06872006-03-01 17:10:01 +0000208 def a():
209 try:
210 yield
211 except:
212 pass
213 def foo():
214 with nested(a(), a()):
215 return 1
216 return 10
217 self.assertEqual(foo(), 1)
218
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000219class ClosingTestCase(unittest.TestCase):
220
221 # XXX This needs more work
222
223 def test_closing(self):
224 state = []
225 class C:
226 def close(self):
227 state.append(1)
228 x = C()
229 self.assertEqual(state, [])
230 with closing(x) as y:
231 self.assertEqual(x, y)
232 self.assertEqual(state, [1])
233
234 def test_closing_error(self):
235 state = []
236 class C:
237 def close(self):
238 state.append(1)
239 x = C()
240 self.assertEqual(state, [])
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000241 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000242 with closing(x) as y:
243 self.assertEqual(x, y)
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000244 1 // 0
245 self.assertEqual(state, [1])
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000246
247class FileContextTestCase(unittest.TestCase):
248
249 def testWithOpen(self):
250 tfn = tempfile.mktemp()
251 try:
252 f = None
253 with open(tfn, "w") as f:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000254 self.assertFalse(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000255 f.write("Booh\n")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000256 self.assertTrue(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000257 f = None
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000258 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000259 with open(tfn, "r") as f:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000260 self.assertFalse(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000261 self.assertEqual(f.read(), "Booh\n")
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000262 1 // 0
263 self.assertTrue(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000264 finally:
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000265 test_support.unlink(tfn)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000266
267class LockContextTestCase(unittest.TestCase):
268
269 def boilerPlate(self, lock, locked):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000270 self.assertFalse(locked())
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000271 with lock:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000272 self.assertTrue(locked())
273 self.assertFalse(locked())
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000274 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000275 with lock:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000276 self.assertTrue(locked())
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000277 1 // 0
278 self.assertFalse(locked())
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000279
280 def testWithLock(self):
281 lock = threading.Lock()
282 self.boilerPlate(lock, lock.locked)
283
284 def testWithRLock(self):
285 lock = threading.RLock()
286 self.boilerPlate(lock, lock._is_owned)
287
288 def testWithCondition(self):
289 lock = threading.Condition()
290 def locked():
291 return lock._is_owned()
292 self.boilerPlate(lock, locked)
293
294 def testWithSemaphore(self):
295 lock = threading.Semaphore()
296 def locked():
297 if lock.acquire(False):
298 lock.release()
299 return False
300 else:
301 return True
302 self.boilerPlate(lock, locked)
303
304 def testWithBoundedSemaphore(self):
305 lock = threading.BoundedSemaphore()
306 def locked():
307 if lock.acquire(False):
308 lock.release()
309 return False
310 else:
311 return True
312 self.boilerPlate(lock, locked)
313
Phillip J. Ebybd0c10f2006-04-10 18:33:17 +0000314# This is needed to make the test actually run under regrtest.py!
315def test_main():
Florent Xicluna6257a7b2010-03-31 22:01:03 +0000316 with test_support.check_warnings(("With-statements now directly support "
317 "multiple context managers",
318 DeprecationWarning)):
Raymond Hettinger822b87f2009-05-29 01:46:48 +0000319 test_support.run_unittest(__name__)
Phillip J. Ebybd0c10f2006-04-10 18:33:17 +0000320
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000321if __name__ == "__main__":
Phillip J. Ebybd0c10f2006-04-10 18:33:17 +0000322 test_main()