bpo-36829: Document test.support.catch_unraisable_exception() (GH-13554) · python/cpython@6dbbe74

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -1081,6 +1081,26 @@ The :mod:`test.support` module defines the following functions:

10811081

:exc:`PermissionError` is raised.

10821082
10831083
1084+

.. function:: catch_unraisable_exception()

1085+
1086+

Context manager catching unraisable exception using

1087+

:func:`sys.unraisablehook`.

1088+
1089+

Usage::

1090+
1091+

with support.catch_unraisable_exception() as cm:

1092+

# code creating an "unraisable exception"

1093+

...

1094+
1095+

# check the unraisable exception: use cm.unraisable

1096+

...

1097+
1098+

# cm.unraisable attribute no longer exists at this point

1099+

# (to break a reference cycle)

1100+
1101+

.. versionadded:: 3.8

1102+
1103+
10841104

.. function:: find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM)

10851105
10861106

Returns an unused port that should be suitable for binding. This is

Original file line numberDiff line numberDiff line change

@@ -3043,12 +3043,14 @@ class catch_unraisable_exception:

30433043

Usage:

30443044
30453045

with support.catch_unraisable_exception() as cm:

3046+

# code creating an "unraisable exception"

30463047

...

30473048
3048-

# check the expected unraisable exception: use cm.unraisable

3049+

# check the unraisable exception: use cm.unraisable

30493050

...

30503051
3051-

# cm.unraisable is None here (to break a reference cycle)

3052+

# cm.unraisable attribute no longer exists at this point

3053+

# (to break a reference cycle)

30523054

"""

30533055
30543056

def __init__(self):

@@ -3065,5 +3067,5 @@ def __enter__(self):

30653067
30663068

def __exit__(self, *exc_info):

30673069

# Clear the unraisable exception to explicitly break a reference cycle

3068-

self.unraisable = None

3070+

del self.unraisable

30693071

sys.unraisablehook = self._old_hook

Original file line numberDiff line numberDiff line change

@@ -1098,18 +1098,14 @@ def test_error_through_destructor(self):

10981098

# Test that the exception state is not modified by a destructor,

10991099

# even if close() fails.

11001100

rawio = self.CloseFailureIO()

1101-

try:

1102-

with support.catch_unraisable_exception() as cm:

1103-

with self.assertRaises(AttributeError):

1104-

self.tp(rawio).xyzzy

1101+

with support.catch_unraisable_exception() as cm:

1102+

with self.assertRaises(AttributeError):

1103+

self.tp(rawio).xyzzy

11051104
11061105

if not IOBASE_EMITS_UNRAISABLE:

11071106

self.assertIsNone(cm.unraisable)

11081107

elif cm.unraisable is not None:

11091108

self.assertEqual(cm.unraisable.exc_type, OSError)

1110-

finally:

1111-

# Explicitly break reference cycle

1112-

cm = None

11131109
11141110

def test_repr(self):

11151111

raw = self.MockRawIO()

@@ -2854,18 +2850,14 @@ def test_error_through_destructor(self):

28542850

# Test that the exception state is not modified by a destructor,

28552851

# even if close() fails.

28562852

rawio = self.CloseFailureIO()

2857-

try:

2858-

with support.catch_unraisable_exception() as cm:

2859-

with self.assertRaises(AttributeError):

2860-

self.TextIOWrapper(rawio).xyzzy

2853+

with support.catch_unraisable_exception() as cm:

2854+

with self.assertRaises(AttributeError):

2855+

self.TextIOWrapper(rawio).xyzzy

28612856
28622857

if not IOBASE_EMITS_UNRAISABLE:

28632858

self.assertIsNone(cm.unraisable)

28642859

elif cm.unraisable is not None:

28652860

self.assertEqual(cm.unraisable.exc_type, OSError)

2866-

finally:

2867-

# Explicitly break reference cycle

2868-

cm = None

28692861
28702862

# Systematic tests of the text I/O API

28712863