blob: c733bcafc7470845e8e1dd3f1f6e998cad2d54a6 [file] [log] [blame]
Guido van Rossum1a5e21e2006-02-28 21:57:43 +00001"""Unit tests for contextlib.py, and other context managers."""
2
R. David Murray378c0cf2010-02-24 01:46:21 +00003import sys
Guido van Rossum1a5e21e2006-02-28 21:57:43 +00004import tempfile
5import unittest
6import threading
7from contextlib import * # Tests __all__
Benjamin Petersonee8712c2008-05-20 21:35:26 +00008from test import support
Guido van Rossum1a5e21e2006-02-28 21:57:43 +00009
Florent Xicluna41fe6152010-04-02 18:52:12 +000010
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000011class ContextManagerTestCase(unittest.TestCase):
12
13 def test_contextmanager_plain(self):
14 state = []
15 @contextmanager
16 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
26 def test_contextmanager_finally(self):
27 state = []
28 @contextmanager
29 def woohoo():
30 state.append(1)
31 try:
32 yield 42
33 finally:
34 state.append(999)
Florent Xicluna41fe6152010-04-02 18:52:12 +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
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000043 def test_contextmanager_no_reraise(self):
44 @contextmanager
45 def whee():
46 yield
Thomas Wouters477c8d52006-05-27 19:21:47 +000047 ctx = whee()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000048 ctx.__enter__()
49 # Calling __exit__ should not result in an exception
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000050 self.assertFalse(ctx.__exit__(TypeError, TypeError("foo"), None))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000051
52 def test_contextmanager_trap_yield_after_throw(self):
53 @contextmanager
54 def whoo():
55 try:
56 yield
57 except:
58 yield
Thomas Wouters477c8d52006-05-27 19:21:47 +000059 ctx = whoo()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000060 ctx.__enter__()
61 self.assertRaises(
62 RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None
63 )
64
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000065 def test_contextmanager_except(self):
66 state = []
67 @contextmanager
68 def woohoo():
69 state.append(1)
70 try:
71 yield 42
Guido van Rossumb940e112007-01-10 16:19:56 +000072 except ZeroDivisionError as e:
Guido van Rossum1a5e21e2006-02-28 21:57:43 +000073 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 Murray378c0cf2010-02-24 01:46:21 +000082 def _create_contextmanager_attribs(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +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
89 @contextmanager
90 @attribs(foo='bar')
91 def baz(spam):
92 """Whee!"""
R. David Murray378c0cf2010-02-24 01:46:21 +000093 return baz
94
95 def test_contextmanager_attribs(self):
96 baz = self._create_contextmanager_attribs()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000097 self.assertEqual(baz.__name__,'baz')
98 self.assertEqual(baz.foo, 'bar')
R. David Murray378c0cf2010-02-24 01:46:21 +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()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000104 self.assertEqual(baz.__doc__, "Whee!")
105
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000106class ClosingTestCase(unittest.TestCase):
107
108 # XXX This needs more work
109
110 def test_closing(self):
111 state = []
112 class C:
113 def close(self):
114 state.append(1)
115 x = C()
116 self.assertEqual(state, [])
117 with closing(x) as y:
118 self.assertEqual(x, y)
119 self.assertEqual(state, [1])
120
121 def test_closing_error(self):
122 state = []
123 class C:
124 def close(self):
125 state.append(1)
126 x = C()
127 self.assertEqual(state, [])
Florent Xicluna41fe6152010-04-02 18:52:12 +0000128 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000129 with closing(x) as y:
130 self.assertEqual(x, y)
Florent Xicluna41fe6152010-04-02 18:52:12 +0000131 1 / 0
132 self.assertEqual(state, [1])
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000133
134class FileContextTestCase(unittest.TestCase):
135
136 def testWithOpen(self):
137 tfn = tempfile.mktemp()
138 try:
139 f = None
140 with open(tfn, "w") as f:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000141 self.assertFalse(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000142 f.write("Booh\n")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000143 self.assertTrue(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000144 f = None
Florent Xicluna41fe6152010-04-02 18:52:12 +0000145 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000146 with open(tfn, "r") as f:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000147 self.assertFalse(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000148 self.assertEqual(f.read(), "Booh\n")
Florent Xicluna41fe6152010-04-02 18:52:12 +0000149 1 / 0
150 self.assertTrue(f.closed)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000151 finally:
Florent Xicluna41fe6152010-04-02 18:52:12 +0000152 support.unlink(tfn)
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000153
154class LockContextTestCase(unittest.TestCase):
155
156 def boilerPlate(self, lock, locked):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000157 self.assertFalse(locked())
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000158 with lock:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000159 self.assertTrue(locked())
160 self.assertFalse(locked())
Florent Xicluna41fe6152010-04-02 18:52:12 +0000161 with self.assertRaises(ZeroDivisionError):
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000162 with lock:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000163 self.assertTrue(locked())
Florent Xicluna41fe6152010-04-02 18:52:12 +0000164 1 / 0
165 self.assertFalse(locked())
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000166
167 def testWithLock(self):
168 lock = threading.Lock()
169 self.boilerPlate(lock, lock.locked)
170
171 def testWithRLock(self):
172 lock = threading.RLock()
173 self.boilerPlate(lock, lock._is_owned)
174
175 def testWithCondition(self):
176 lock = threading.Condition()
177 def locked():
178 return lock._is_owned()
179 self.boilerPlate(lock, locked)
180
181 def testWithSemaphore(self):
182 lock = threading.Semaphore()
183 def locked():
184 if lock.acquire(False):
185 lock.release()
186 return False
187 else:
188 return True
189 self.boilerPlate(lock, locked)
190
191 def testWithBoundedSemaphore(self):
192 lock = threading.BoundedSemaphore()
193 def locked():
194 if lock.acquire(False):
195 lock.release()
196 return False
197 else:
198 return True
199 self.boilerPlate(lock, locked)
200
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000201# This is needed to make the test actually run under regrtest.py!
202def test_main():
Benjamin Petersonc8c0d782009-07-01 01:39:51 +0000203 support.run_unittest(__name__)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000204
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000205if __name__ == "__main__":
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206 test_main()