Commit 6dbbe748 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-36829: Document test.support.catch_unraisable_exception() (GH-13554)

catch_unraisable_exception() now also removes its 'unraisable'
attribute at the context manager exit.
parent a9f05d69
...@@ -1081,6 +1081,26 @@ The :mod:`test.support` module defines the following functions: ...@@ -1081,6 +1081,26 @@ The :mod:`test.support` module defines the following functions:
:exc:`PermissionError` is raised. :exc:`PermissionError` is raised.
.. function:: catch_unraisable_exception()
Context manager catching unraisable exception using
:func:`sys.unraisablehook`.
Usage::
with support.catch_unraisable_exception() as cm:
# code creating an "unraisable exception"
...
# check the unraisable exception: use cm.unraisable
...
# cm.unraisable attribute no longer exists at this point
# (to break a reference cycle)
.. versionadded:: 3.8
.. function:: find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM) .. function:: find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM)
Returns an unused port that should be suitable for binding. This is Returns an unused port that should be suitable for binding. This is
......
...@@ -3043,12 +3043,14 @@ class catch_unraisable_exception: ...@@ -3043,12 +3043,14 @@ class catch_unraisable_exception:
Usage: Usage:
with support.catch_unraisable_exception() as cm: with support.catch_unraisable_exception() as cm:
# code creating an "unraisable exception"
... ...
# check the expected unraisable exception: use cm.unraisable # check the unraisable exception: use cm.unraisable
... ...
# cm.unraisable is None here (to break a reference cycle) # cm.unraisable attribute no longer exists at this point
# (to break a reference cycle)
""" """
def __init__(self): def __init__(self):
...@@ -3065,5 +3067,5 @@ class catch_unraisable_exception: ...@@ -3065,5 +3067,5 @@ class catch_unraisable_exception:
def __exit__(self, *exc_info): def __exit__(self, *exc_info):
# Clear the unraisable exception to explicitly break a reference cycle # Clear the unraisable exception to explicitly break a reference cycle
self.unraisable = None del self.unraisable
sys.unraisablehook = self._old_hook sys.unraisablehook = self._old_hook
...@@ -1098,7 +1098,6 @@ class CommonBufferedTests: ...@@ -1098,7 +1098,6 @@ class CommonBufferedTests:
# Test that the exception state is not modified by a destructor, # Test that the exception state is not modified by a destructor,
# even if close() fails. # even if close() fails.
rawio = self.CloseFailureIO() rawio = self.CloseFailureIO()
try:
with support.catch_unraisable_exception() as cm: with support.catch_unraisable_exception() as cm:
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
self.tp(rawio).xyzzy self.tp(rawio).xyzzy
...@@ -1107,9 +1106,6 @@ class CommonBufferedTests: ...@@ -1107,9 +1106,6 @@ class CommonBufferedTests:
self.assertIsNone(cm.unraisable) self.assertIsNone(cm.unraisable)
elif cm.unraisable is not None: elif cm.unraisable is not None:
self.assertEqual(cm.unraisable.exc_type, OSError) self.assertEqual(cm.unraisable.exc_type, OSError)
finally:
# Explicitly break reference cycle
cm = None
def test_repr(self): def test_repr(self):
raw = self.MockRawIO() raw = self.MockRawIO()
...@@ -2854,7 +2850,6 @@ class TextIOWrapperTest(unittest.TestCase): ...@@ -2854,7 +2850,6 @@ class TextIOWrapperTest(unittest.TestCase):
# Test that the exception state is not modified by a destructor, # Test that the exception state is not modified by a destructor,
# even if close() fails. # even if close() fails.
rawio = self.CloseFailureIO() rawio = self.CloseFailureIO()
try:
with support.catch_unraisable_exception() as cm: with support.catch_unraisable_exception() as cm:
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
self.TextIOWrapper(rawio).xyzzy self.TextIOWrapper(rawio).xyzzy
...@@ -2863,9 +2858,6 @@ class TextIOWrapperTest(unittest.TestCase): ...@@ -2863,9 +2858,6 @@ class TextIOWrapperTest(unittest.TestCase):
self.assertIsNone(cm.unraisable) self.assertIsNone(cm.unraisable)
elif cm.unraisable is not None: elif cm.unraisable is not None:
self.assertEqual(cm.unraisable.exc_type, OSError) self.assertEqual(cm.unraisable.exc_type, OSError)
finally:
# Explicitly break reference cycle
cm = None
# Systematic tests of the text I/O API # Systematic tests of the text I/O API
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment