kopia lustrzana https://github.com/micropython/micropython-lib
contextlib: modify TestExitStack to work in uPy
rodzic
b9f3b49e2e
commit
1773bc0788
|
@ -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__':
|
||||||
|
|
Ładowanie…
Reference in New Issue