contextlib: modify TestExitStack to work in uPy

pull/53/head
Delio Brignoli 2015-10-22 00:40:32 +02:00 zatwierdzone przez Paul Sokolovsky
rodzic b9f3b49e2e
commit 1773bc0788
1 zmienionych plików z 40 dodań i 25 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
import sys
import unittest import unittest
from contextlib import closing, suppress from contextlib import closing, suppress, ExitStack
class ClosingTestCase(unittest.TestCase): class ClosingTestCase(unittest.TestCase):
@ -39,8 +40,8 @@ class SuppressTestCase(unittest.TestCase):
class TestExitStack(unittest.TestCase): class TestExitStack(unittest.TestCase):
@support.requires_docstrings # @support.requires_docstrings
def test_instance_docs(self): def _test_instance_docs(self):
# Issue 19330: ensure context manager instances have good docstrings # Issue 19330: ensure context manager instances have good docstrings
cm_docstring = ExitStack.__doc__ cm_docstring = ExitStack.__doc__
obj = ExitStack() obj = ExitStack()
@ -74,10 +75,10 @@ class TestExitStack(unittest.TestCase):
else: else:
f = stack.callback(_exit) f = stack.callback(_exit)
self.assertIs(f, _exit) self.assertIs(f, _exit)
for wrapper in stack._exit_callbacks: # for wrapper in stack._exit_callbacks:
self.assertIs(wrapper.__wrapped__, _exit) # self.assertIs(wrapper.__wrapped__, _exit)
self.assertNotEqual(wrapper.__name__, _exit.__name__) # self.assertNotEqual(wrapper.__name__, _exit.__name__)
self.assertIsNone(wrapper.__doc__, _exit.__doc__) # self.assertIsNone(wrapper.__doc__, _exit.__doc__)
self.assertEqual(result, expected) self.assertEqual(result, expected)
def test_push(self): def test_push(self):
@ -99,19 +100,19 @@ class TestExitStack(unittest.TestCase):
self.check_exc(*exc_details) self.check_exc(*exc_details)
with ExitStack() as stack: with ExitStack() as stack:
stack.push(_expect_ok) stack.push(_expect_ok)
self.assertIs(stack._exit_callbacks[-1], _expect_ok) self.assertIs(tuple(stack._exit_callbacks)[-1], _expect_ok)
cm = ExitCM(_expect_ok) cm = ExitCM(_expect_ok)
stack.push(cm) stack.push(cm)
self.assertIs(stack._exit_callbacks[-1].__self__, cm) # self.assertIs(stack._exit_callbacks[-1].__self__, cm)
stack.push(_suppress_exc) stack.push(_suppress_exc)
self.assertIs(stack._exit_callbacks[-1], _suppress_exc) self.assertIs(tuple(stack._exit_callbacks)[-1], _suppress_exc)
cm = ExitCM(_expect_exc) cm = ExitCM(_expect_exc)
stack.push(cm) stack.push(cm)
self.assertIs(stack._exit_callbacks[-1].__self__, cm) # self.assertIs(stack._exit_callbacks[-1].__self__, cm)
stack.push(_expect_exc) stack.push(_expect_exc)
self.assertIs(stack._exit_callbacks[-1], _expect_exc) self.assertIs(tuple(stack._exit_callbacks)[-1], _expect_exc)
stack.push(_expect_exc) stack.push(_expect_exc)
self.assertIs(stack._exit_callbacks[-1], _expect_exc) self.assertIs(tuple(stack._exit_callbacks)[-1], _expect_exc)
1/0 1/0
def test_enter_context(self): def test_enter_context(self):
@ -129,7 +130,7 @@ class TestExitStack(unittest.TestCase):
result.append(4) result.append(4)
self.assertIsNotNone(_exit) self.assertIsNotNone(_exit)
stack.enter_context(cm) stack.enter_context(cm)
self.assertIs(stack._exit_callbacks[-1].__self__, cm) # self.assertIs(stack._exit_callbacks[-1].__self__, cm)
result.append(2) result.append(2)
self.assertEqual(result, [1, 2, 3, 4]) self.assertEqual(result, [1, 2, 3, 4])
@ -171,12 +172,14 @@ class TestExitStack(unittest.TestCase):
def test_exit_exception_chaining_reference(self): def test_exit_exception_chaining_reference(self):
# Sanity check to make sure that ExitStack chaining matches # Sanity check to make sure that ExitStack chaining matches
# actual nested with statements # actual nested with statements
exc_chain = []
class RaiseExc: class RaiseExc:
def __init__(self, exc): def __init__(self, exc):
self.exc = exc self.exc = exc
def __enter__(self): def __enter__(self):
return self return self
def __exit__(self, *exc_details): def __exit__(self, *exc_details):
exc_chain.append(exc_details[0])
raise self.exc raise self.exc
class RaiseExcWithContext: class RaiseExcWithContext:
@ -187,8 +190,10 @@ class TestExitStack(unittest.TestCase):
return self return self
def __exit__(self, *exc_details): def __exit__(self, *exc_details):
try: try:
exc_chain.append(exc_details[0])
raise self.inner raise self.inner
except: except:
exc_chain.append(sys.exc_info()[0])
raise self.outer raise self.outer
class SuppressExc: class SuppressExc:
@ -205,26 +210,35 @@ class TestExitStack(unittest.TestCase):
with RaiseExc(ValueError): with RaiseExc(ValueError):
1 / 0 1 / 0
except IndexError as exc: except IndexError as exc:
self.assertIsInstance(exc.__context__, KeyError) # self.assertIsInstance(exc.__context__, KeyError)
self.assertIsInstance(exc.__context__.__context__, AttributeError) # self.assertIsInstance(exc.__context__.__context__, AttributeError)
# Inner exceptions were suppressed # Inner exceptions were suppressed
self.assertIsNone(exc.__context__.__context__.__context__) # self.assertIsNone(exc.__context__.__context__.__context__)
exc_chain.append(type(exc))
assert tuple(exc_chain) == (ZeroDivisionError, None, AttributeError, KeyError, IndexError)
else: else:
self.fail("Expected IndexError, but no exception was raised") self.fail("Expected IndexError, but no exception was raised")
# Check the inner exceptions # Check the inner exceptions
inner_exc = SuppressExc.saved_details[1] inner_exc = SuppressExc.saved_details[1]
self.assertIsInstance(inner_exc, ValueError) self.assertIsInstance(inner_exc, ValueError)
self.assertIsInstance(inner_exc.__context__, ZeroDivisionError) # self.assertIsInstance(inner_exc.__context__, ZeroDivisionError)
def test_exit_exception_chaining(self): def test_exit_exception_chaining(self):
# Ensure exception chaining matches the reference behaviour # Ensure exception chaining matches the reference behaviour
exc_chain = []
def raise_exc(exc): def raise_exc(exc):
frame_exc = sys.exc_info()[0]
if frame_exc is not None:
exc_chain.append(frame_exc)
exc_chain.append(exc)
raise exc raise exc
saved_details = None saved_details = None
def suppress_exc(*exc_details): def suppress_exc(*exc_details):
nonlocal saved_details nonlocal saved_details
saved_details = exc_details saved_details = exc_details
assert exc_chain[-1] == exc_details[0]
exc_chain[-1] = None
return True return True
try: try:
@ -236,16 +250,17 @@ class TestExitStack(unittest.TestCase):
stack.callback(raise_exc, ValueError) stack.callback(raise_exc, ValueError)
1 / 0 1 / 0
except IndexError as exc: except IndexError as exc:
self.assertIsInstance(exc.__context__, KeyError) # self.assertIsInstance(exc.__context__, KeyError)
self.assertIsInstance(exc.__context__.__context__, AttributeError) # self.assertIsInstance(exc.__context__.__context__, AttributeError)
# Inner exceptions were suppressed # Inner exceptions were suppressed
self.assertIsNone(exc.__context__.__context__.__context__) # self.assertIsNone(exc.__context__.__context__.__context__)
assert tuple(exc_chain) == (ZeroDivisionError, None, AttributeError, KeyError, IndexError)
else: else:
self.fail("Expected IndexError, but no exception was raised") self.fail("Expected IndexError, but no exception was raised")
# Check the inner exceptions # Check the inner exceptions
inner_exc = saved_details[1] inner_exc = saved_details[1]
self.assertIsInstance(inner_exc, ValueError) self.assertIsInstance(inner_exc, ValueError)
self.assertIsInstance(inner_exc.__context__, ZeroDivisionError) # self.assertIsInstance(inner_exc.__context__, ZeroDivisionError)
def test_exit_exception_non_suppressing(self): def test_exit_exception_non_suppressing(self):
# http://bugs.python.org/issue19092 # http://bugs.python.org/issue19092
@ -274,7 +289,7 @@ class TestExitStack(unittest.TestCase):
else: else:
self.fail("Expected KeyError, but no exception was raised") self.fail("Expected KeyError, but no exception was raised")
def test_exit_exception_with_correct_context(self): def _test_exit_exception_with_correct_context(self):
# http://bugs.python.org/issue20317 # http://bugs.python.org/issue20317
@contextmanager @contextmanager
def gets_the_context_right(exc): def gets_the_context_right(exc):
@ -305,7 +320,7 @@ class TestExitStack(unittest.TestCase):
self.assertIsNone( self.assertIsNone(
exc.__context__.__context__.__context__.__context__) exc.__context__.__context__.__context__.__context__)
def test_exit_exception_with_existing_context(self): def _test_exit_exception_with_existing_context(self):
# Addresses a lack of test coverage discovered after checking in a # Addresses a lack of test coverage discovered after checking in a
# fix for issue 20317 that still contained debugging code. # fix for issue 20317 that still contained debugging code.
def raise_nested(inner_exc, outer_exc): def raise_nested(inner_exc, outer_exc):
@ -364,7 +379,7 @@ class TestExitStack(unittest.TestCase):
stack = ExitStack() stack = ExitStack()
self.assertRaises(AttributeError, stack.enter_context, cm) self.assertRaises(AttributeError, stack.enter_context, cm)
stack.push(cm) stack.push(cm)
self.assertIs(stack._exit_callbacks[-1], cm) self.assertIs(tuple(stack._exit_callbacks)[-1], cm)
if __name__ == '__main__': if __name__ == '__main__':