2006-02-28 17:57:43 -04:00
|
|
|
"""Unit tests for contextlib.py, and other context managers."""
|
|
|
|
|
2010-02-22 20:24:49 -04:00
|
|
|
import sys
|
2006-02-28 17:57:43 -04:00
|
|
|
import tempfile
|
|
|
|
import unittest
|
|
|
|
from contextlib import * # Tests __all__
|
2007-04-25 14:29:52 -03:00
|
|
|
from test import test_support
|
2010-04-27 20:55:59 -03:00
|
|
|
try:
|
|
|
|
import threading
|
|
|
|
except ImportError:
|
|
|
|
threading = None
|
2010-03-31 19:01:03 -03:00
|
|
|
|
2006-02-28 17:57:43 -04:00
|
|
|
|
|
|
|
class ContextManagerTestCase(unittest.TestCase):
|
|
|
|
|
2006-05-03 10:02:47 -03:00
|
|
|
def test_contextmanager_plain(self):
|
2006-02-28 17:57:43 -04:00
|
|
|
state = []
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def woohoo():
|
|
|
|
state.append(1)
|
|
|
|
yield 42
|
|
|
|
state.append(999)
|
|
|
|
with woohoo() as x:
|
|
|
|
self.assertEqual(state, [1])
|
|
|
|
self.assertEqual(x, 42)
|
|
|
|
state.append(x)
|
|
|
|
self.assertEqual(state, [1, 42, 999])
|
|
|
|
|
2006-05-03 10:02:47 -03:00
|
|
|
def test_contextmanager_finally(self):
|
2006-02-28 17:57:43 -04:00
|
|
|
state = []
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def woohoo():
|
|
|
|
state.append(1)
|
|
|
|
try:
|
|
|
|
yield 42
|
|
|
|
finally:
|
|
|
|
state.append(999)
|
2010-03-31 19:01:03 -03:00
|
|
|
with self.assertRaises(ZeroDivisionError):
|
2006-02-28 17:57:43 -04:00
|
|
|
with woohoo() as x:
|
|
|
|
self.assertEqual(state, [1])
|
|
|
|
self.assertEqual(x, 42)
|
|
|
|
state.append(x)
|
|
|
|
raise ZeroDivisionError()
|
|
|
|
self.assertEqual(state, [1, 42, 999])
|
|
|
|
|
2006-05-03 10:02:47 -03:00
|
|
|
def test_contextmanager_no_reraise(self):
|
|
|
|
@contextmanager
|
2006-03-24 20:28:24 -04:00
|
|
|
def whee():
|
|
|
|
yield
|
2006-05-02 16:47:52 -03:00
|
|
|
ctx = whee()
|
2006-03-24 20:28:24 -04:00
|
|
|
ctx.__enter__()
|
|
|
|
# Calling __exit__ should not result in an exception
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertFalse(ctx.__exit__(TypeError, TypeError("foo"), None))
|
2006-03-24 20:28:24 -04:00
|
|
|
|
2006-05-03 10:02:47 -03:00
|
|
|
def test_contextmanager_trap_yield_after_throw(self):
|
|
|
|
@contextmanager
|
2006-03-24 20:28:24 -04:00
|
|
|
def whoo():
|
|
|
|
try:
|
|
|
|
yield
|
|
|
|
except:
|
|
|
|
yield
|
2006-05-02 16:47:52 -03:00
|
|
|
ctx = whoo()
|
2006-03-24 20:28:24 -04:00
|
|
|
ctx.__enter__()
|
|
|
|
self.assertRaises(
|
|
|
|
RuntimeError, ctx.__exit__, TypeError, TypeError("foo"), None
|
|
|
|
)
|
|
|
|
|
2006-05-03 10:02:47 -03:00
|
|
|
def test_contextmanager_except(self):
|
2006-02-28 17:57:43 -04:00
|
|
|
state = []
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def woohoo():
|
|
|
|
state.append(1)
|
|
|
|
try:
|
|
|
|
yield 42
|
|
|
|
except ZeroDivisionError, e:
|
|
|
|
state.append(e.args[0])
|
|
|
|
self.assertEqual(state, [1, 42, 999])
|
|
|
|
with woohoo() as x:
|
|
|
|
self.assertEqual(state, [1])
|
|
|
|
self.assertEqual(x, 42)
|
|
|
|
state.append(x)
|
|
|
|
raise ZeroDivisionError(999)
|
|
|
|
self.assertEqual(state, [1, 42, 999])
|
|
|
|
|
2010-02-22 20:24:49 -04:00
|
|
|
def _create_contextmanager_attribs(self):
|
2006-03-27 20:07:24 -04:00
|
|
|
def attribs(**kw):
|
|
|
|
def decorate(func):
|
|
|
|
for k,v in kw.items():
|
|
|
|
setattr(func,k,v)
|
|
|
|
return func
|
|
|
|
return decorate
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-03-27 20:07:24 -04:00
|
|
|
@attribs(foo='bar')
|
|
|
|
def baz(spam):
|
|
|
|
"""Whee!"""
|
2010-02-22 20:24:49 -04:00
|
|
|
return baz
|
|
|
|
|
|
|
|
def test_contextmanager_attribs(self):
|
|
|
|
baz = self._create_contextmanager_attribs()
|
2006-03-27 20:07:24 -04:00
|
|
|
self.assertEqual(baz.__name__,'baz')
|
|
|
|
self.assertEqual(baz.foo, 'bar')
|
2010-02-22 20:24:49 -04:00
|
|
|
|
|
|
|
@unittest.skipIf(sys.flags.optimize >= 2,
|
|
|
|
"Docstrings are omitted with -O2 and above")
|
|
|
|
def test_contextmanager_doc_attrib(self):
|
|
|
|
baz = self._create_contextmanager_attribs()
|
2006-03-27 20:07:24 -04:00
|
|
|
self.assertEqual(baz.__doc__, "Whee!")
|
|
|
|
|
2006-02-28 17:57:43 -04:00
|
|
|
class NestedTestCase(unittest.TestCase):
|
|
|
|
|
|
|
|
# XXX This needs more work
|
|
|
|
|
|
|
|
def test_nested(self):
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def a():
|
|
|
|
yield 1
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def b():
|
|
|
|
yield 2
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def c():
|
|
|
|
yield 3
|
|
|
|
with nested(a(), b(), c()) as (x, y, z):
|
|
|
|
self.assertEqual(x, 1)
|
|
|
|
self.assertEqual(y, 2)
|
|
|
|
self.assertEqual(z, 3)
|
|
|
|
|
|
|
|
def test_nested_cleanup(self):
|
|
|
|
state = []
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def a():
|
|
|
|
state.append(1)
|
|
|
|
try:
|
|
|
|
yield 2
|
|
|
|
finally:
|
|
|
|
state.append(3)
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-02-28 17:57:43 -04:00
|
|
|
def b():
|
|
|
|
state.append(4)
|
|
|
|
try:
|
|
|
|
yield 5
|
|
|
|
finally:
|
|
|
|
state.append(6)
|
2010-03-31 19:01:03 -03:00
|
|
|
with self.assertRaises(ZeroDivisionError):
|
2006-02-28 17:57:43 -04:00
|
|
|
with nested(a(), b()) as (x, y):
|
|
|
|
state.append(x)
|
|
|
|
state.append(y)
|
2010-03-31 19:01:03 -03:00
|
|
|
1 // 0
|
|
|
|
self.assertEqual(state, [1, 4, 2, 5, 6, 3])
|
2006-02-28 17:57:43 -04:00
|
|
|
|
2006-04-24 01:37:15 -03:00
|
|
|
def test_nested_right_exception(self):
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-04-24 01:37:15 -03:00
|
|
|
def a():
|
|
|
|
yield 1
|
|
|
|
class b(object):
|
|
|
|
def __enter__(self):
|
|
|
|
return 2
|
|
|
|
def __exit__(self, *exc_info):
|
|
|
|
try:
|
|
|
|
raise Exception()
|
|
|
|
except:
|
|
|
|
pass
|
2010-03-31 19:01:03 -03:00
|
|
|
with self.assertRaises(ZeroDivisionError):
|
2006-04-24 01:37:15 -03:00
|
|
|
with nested(a(), b()) as (x, y):
|
2010-03-31 19:01:03 -03:00
|
|
|
1 // 0
|
|
|
|
self.assertEqual((x, y), (1, 2))
|
2006-04-24 01:37:15 -03:00
|
|
|
|
2006-03-01 13:10:01 -04:00
|
|
|
def test_nested_b_swallows(self):
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-03-01 13:10:01 -04:00
|
|
|
def a():
|
|
|
|
yield
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-03-01 13:10:01 -04:00
|
|
|
def b():
|
|
|
|
try:
|
|
|
|
yield
|
|
|
|
except:
|
|
|
|
# Swallow the exception
|
|
|
|
pass
|
|
|
|
try:
|
|
|
|
with nested(a(), b()):
|
2010-03-31 19:01:03 -03:00
|
|
|
1 // 0
|
2006-03-01 13:10:01 -04:00
|
|
|
except ZeroDivisionError:
|
|
|
|
self.fail("Didn't swallow ZeroDivisionError")
|
|
|
|
|
|
|
|
def test_nested_break(self):
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-03-01 13:10:01 -04:00
|
|
|
def a():
|
|
|
|
yield
|
|
|
|
state = 0
|
|
|
|
while True:
|
|
|
|
state += 1
|
|
|
|
with nested(a(), a()):
|
|
|
|
break
|
|
|
|
state += 10
|
|
|
|
self.assertEqual(state, 1)
|
|
|
|
|
|
|
|
def test_nested_continue(self):
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-03-01 13:10:01 -04:00
|
|
|
def a():
|
|
|
|
yield
|
|
|
|
state = 0
|
|
|
|
while state < 3:
|
|
|
|
state += 1
|
|
|
|
with nested(a(), a()):
|
|
|
|
continue
|
|
|
|
state += 10
|
|
|
|
self.assertEqual(state, 3)
|
|
|
|
|
|
|
|
def test_nested_return(self):
|
2006-05-03 10:02:47 -03:00
|
|
|
@contextmanager
|
2006-03-01 13:10:01 -04:00
|
|
|
def a():
|
|
|
|
try:
|
|
|
|
yield
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
def foo():
|
|
|
|
with nested(a(), a()):
|
|
|
|
return 1
|
|
|
|
return 10
|
|
|
|
self.assertEqual(foo(), 1)
|
|
|
|
|
2006-02-28 17:57:43 -04:00
|
|
|
class ClosingTestCase(unittest.TestCase):
|
|
|
|
|
|
|
|
# XXX This needs more work
|
|
|
|
|
|
|
|
def test_closing(self):
|
|
|
|
state = []
|
|
|
|
class C:
|
|
|
|
def close(self):
|
|
|
|
state.append(1)
|
|
|
|
x = C()
|
|
|
|
self.assertEqual(state, [])
|
|
|
|
with closing(x) as y:
|
|
|
|
self.assertEqual(x, y)
|
|
|
|
self.assertEqual(state, [1])
|
|
|
|
|
|
|
|
def test_closing_error(self):
|
|
|
|
state = []
|
|
|
|
class C:
|
|
|
|
def close(self):
|
|
|
|
state.append(1)
|
|
|
|
x = C()
|
|
|
|
self.assertEqual(state, [])
|
2010-03-31 19:01:03 -03:00
|
|
|
with self.assertRaises(ZeroDivisionError):
|
2006-02-28 17:57:43 -04:00
|
|
|
with closing(x) as y:
|
|
|
|
self.assertEqual(x, y)
|
2010-03-31 19:01:03 -03:00
|
|
|
1 // 0
|
|
|
|
self.assertEqual(state, [1])
|
2006-02-28 17:57:43 -04:00
|
|
|
|
|
|
|
class FileContextTestCase(unittest.TestCase):
|
|
|
|
|
|
|
|
def testWithOpen(self):
|
|
|
|
tfn = tempfile.mktemp()
|
|
|
|
try:
|
|
|
|
f = None
|
|
|
|
with open(tfn, "w") as f:
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertFalse(f.closed)
|
2006-02-28 17:57:43 -04:00
|
|
|
f.write("Booh\n")
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertTrue(f.closed)
|
2006-02-28 17:57:43 -04:00
|
|
|
f = None
|
2010-03-31 19:01:03 -03:00
|
|
|
with self.assertRaises(ZeroDivisionError):
|
2006-02-28 17:57:43 -04:00
|
|
|
with open(tfn, "r") as f:
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertFalse(f.closed)
|
2006-02-28 17:57:43 -04:00
|
|
|
self.assertEqual(f.read(), "Booh\n")
|
2010-03-31 19:01:03 -03:00
|
|
|
1 // 0
|
|
|
|
self.assertTrue(f.closed)
|
2006-02-28 17:57:43 -04:00
|
|
|
finally:
|
2010-03-31 19:01:03 -03:00
|
|
|
test_support.unlink(tfn)
|
2006-02-28 17:57:43 -04:00
|
|
|
|
2010-04-27 20:55:59 -03:00
|
|
|
@unittest.skipUnless(threading, 'Threading required for this test.')
|
2006-02-28 17:57:43 -04:00
|
|
|
class LockContextTestCase(unittest.TestCase):
|
|
|
|
|
|
|
|
def boilerPlate(self, lock, locked):
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertFalse(locked())
|
2006-02-28 17:57:43 -04:00
|
|
|
with lock:
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertTrue(locked())
|
|
|
|
self.assertFalse(locked())
|
2010-03-31 19:01:03 -03:00
|
|
|
with self.assertRaises(ZeroDivisionError):
|
2006-02-28 17:57:43 -04:00
|
|
|
with lock:
|
2009-06-30 19:57:08 -03:00
|
|
|
self.assertTrue(locked())
|
2010-03-31 19:01:03 -03:00
|
|
|
1 // 0
|
|
|
|
self.assertFalse(locked())
|
2006-02-28 17:57:43 -04:00
|
|
|
|
|
|
|
def testWithLock(self):
|
|
|
|
lock = threading.Lock()
|
|
|
|
self.boilerPlate(lock, lock.locked)
|
|
|
|
|
|
|
|
def testWithRLock(self):
|
|
|
|
lock = threading.RLock()
|
|
|
|
self.boilerPlate(lock, lock._is_owned)
|
|
|
|
|
|
|
|
def testWithCondition(self):
|
|
|
|
lock = threading.Condition()
|
|
|
|
def locked():
|
|
|
|
return lock._is_owned()
|
|
|
|
self.boilerPlate(lock, locked)
|
|
|
|
|
|
|
|
def testWithSemaphore(self):
|
|
|
|
lock = threading.Semaphore()
|
|
|
|
def locked():
|
|
|
|
if lock.acquire(False):
|
|
|
|
lock.release()
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
self.boilerPlate(lock, locked)
|
|
|
|
|
|
|
|
def testWithBoundedSemaphore(self):
|
|
|
|
lock = threading.BoundedSemaphore()
|
|
|
|
def locked():
|
|
|
|
if lock.acquire(False):
|
|
|
|
lock.release()
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
self.boilerPlate(lock, locked)
|
|
|
|
|
2006-04-10 15:33:17 -03:00
|
|
|
# This is needed to make the test actually run under regrtest.py!
|
|
|
|
def test_main():
|
2010-03-31 19:01:03 -03:00
|
|
|
with test_support.check_warnings(("With-statements now directly support "
|
|
|
|
"multiple context managers",
|
|
|
|
DeprecationWarning)):
|
2009-05-28 22:46:48 -03:00
|
|
|
test_support.run_unittest(__name__)
|
2006-04-10 15:33:17 -03:00
|
|
|
|
2006-02-28 17:57:43 -04:00
|
|
|
if __name__ == "__main__":
|
2006-04-10 15:33:17 -03:00
|
|
|
test_main()
|