Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-102799: use sys.exception() instead of sys.exc_info() in tests #103293

Merged
merged 9 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Lib/test/profilee.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def helper1():
TICKS += 19
lst = []
lst.append(42) # 0
sys.exc_info() # 0
sys.exception() # 0

def helper2_indirect():
helper2() # 50
Expand Down
7 changes: 4 additions & 3 deletions Lib/test/support/asyncore.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,11 @@ def send(self, data):
# ---------------------------------------------------------------------------

def compact_traceback():
t, v, tb = sys.exc_info()
tbinfo = []
exc = sys.exception()
tb = exc.__traceback__
if not tb: # Must have a traceback
raise AssertionError("traceback does not exist")
tbinfo = []
while tb:
tbinfo.append((
tb.tb_frame.f_code.co_filename,
Expand All @@ -554,7 +555,7 @@ def compact_traceback():

file, function, line = tbinfo[-1]
info = ' '.join(['[%s|%s|%s]' % x for x in tbinfo])
return (file, function, line), t, v, info
return (file, function, line), type(exc), exc, info

def close_all(map=None, ignore_all=False):
if map is None:
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ def on_timeout():
if (
timed_out
and task.uncancel() == 0
and sys.exc_info()[0] is asyncio.CancelledError
and type(sys.exception()) is asyncio.CancelledError
):
# Note the five rules that are needed here to satisfy proper
# uncancellation:
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_asyncio/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ def tearDown(self):

# Detect CPython bug #23353: ensure that yield/yield-from is not used
# in an except block of a generator
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

self.doCleanups()
threading_helper.threading_cleanup(*self._thread_cleanup)
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ def __init__(self):
a = A()
self.assertEqual(_testcapi.hasattr_string(a, "attr"), True)
self.assertEqual(_testcapi.hasattr_string(a, "noattr"), False)
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def testDel(self):
x = []
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_cprofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def main():
profilee.py:98(subhelper) <- 8 0.064 0.080 profilee.py:88(helper2)
{built-in method builtins.hasattr} <- 4 0.000 0.004 profilee.py:73(helper1)
8 0.000 0.008 profilee.py:88(helper2)
{built-in method sys.exc_info} <- 4 0.000 0.000 profilee.py:73(helper1)
{built-in method sys.exception} <- 4 0.000 0.000 profilee.py:73(helper1)
{method 'append' of 'list' objects} <- 4 0.000 0.000 profilee.py:73(helper1)"""
_ProfileOutput['print_callees'] = """\
<string>:1(<module>) -> 1 0.270 1.000 profilee.py:25(testfunc)
Expand Down
66 changes: 32 additions & 34 deletions Lib/test/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,7 @@ def test_capi1():
try:
_testcapi.raise_exception(BadException, 1)
except TypeError as err:
exc, err, tb = sys.exc_info()
co = tb.tb_frame.f_code
co = err.__traceback__.tb_frame.f_code
self.assertEqual(co.co_name, "test_capi1")
self.assertTrue(co.co_filename.endswith('test_exceptions.py'))
else:
Expand All @@ -346,8 +345,7 @@ def test_capi2():
try:
_testcapi.raise_exception(BadException, 0)
except RuntimeError as err:
exc, err, tb = sys.exc_info()
tb = tb.tb_next
tb = err.__traceback__.tb_next
co = tb.tb_frame.f_code
self.assertEqual(co.co_name, "__init__")
self.assertTrue(co.co_filename.endswith('test_exceptions.py'))
Expand Down Expand Up @@ -888,28 +886,28 @@ def yield_raise():
try:
raise KeyError("caught")
except KeyError:
yield sys.exc_info()[0]
yield sys.exc_info()[0]
yield sys.exc_info()[0]
yield sys.exception()
yield sys.exception()
yield sys.exception()
g = yield_raise()
self.assertEqual(next(g), KeyError)
self.assertEqual(sys.exc_info()[0], None)
self.assertEqual(next(g), KeyError)
self.assertEqual(sys.exc_info()[0], None)
self.assertEqual(next(g), None)
self.assertIsInstance(next(g), KeyError)
self.assertIsNone(sys.exception())
self.assertIsInstance(next(g), KeyError)
self.assertIsNone(sys.exception())
self.assertIsNone(next(g))

# Same test, but inside an exception handler
try:
raise TypeError("foo")
except TypeError:
g = yield_raise()
self.assertEqual(next(g), KeyError)
self.assertEqual(sys.exc_info()[0], TypeError)
self.assertEqual(next(g), KeyError)
self.assertEqual(sys.exc_info()[0], TypeError)
self.assertEqual(next(g), TypeError)
self.assertIsInstance(next(g), KeyError)
self.assertIsInstance(sys.exception(), TypeError)
self.assertIsInstance(next(g), KeyError)
self.assertIsInstance(sys.exception(), TypeError)
self.assertIsInstance(next(g), TypeError)
del g
self.assertEqual(sys.exc_info()[0], TypeError)
self.assertIsInstance(sys.exception(), TypeError)

def test_generator_leaking2(self):
# See issue 12475.
Expand All @@ -924,7 +922,7 @@ def g():
next(it)
except StopIteration:
pass
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_generator_leaking3(self):
# See issue #23353. When gen.throw() is called, the caller's
Expand All @@ -933,17 +931,17 @@ def g():
try:
yield
except ZeroDivisionError:
yield sys.exc_info()[1]
yield sys.exception()
it = g()
next(it)
try:
1/0
except ZeroDivisionError as e:
self.assertIs(sys.exc_info()[1], e)
self.assertIs(sys.exception(), e)
gen_exc = it.throw(e)
self.assertIs(sys.exc_info()[1], e)
self.assertIs(sys.exception(), e)
self.assertIs(gen_exc, e)
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_generator_leaking4(self):
# See issue #23353. When an exception is raised by a generator,
Expand All @@ -952,39 +950,39 @@ def g():
try:
1/0
except ZeroDivisionError:
yield sys.exc_info()[0]
yield sys.exception()
raise
it = g()
try:
raise TypeError
except TypeError:
# The caller's exception state (TypeError) is temporarily
# saved in the generator.
tp = next(it)
tp = type(next(it))
self.assertIs(tp, ZeroDivisionError)
try:
next(it)
# We can't check it immediately, but while next() returns
# with an exception, it shouldn't have restored the old
# exception state (TypeError).
except ZeroDivisionError as e:
self.assertIs(sys.exc_info()[1], e)
self.assertIs(sys.exception(), e)
# We used to find TypeError here.
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_generator_doesnt_retain_old_exc(self):
def g():
self.assertIsInstance(sys.exc_info()[1], RuntimeError)
self.assertIsInstance(sys.exception(), RuntimeError)
yield
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())
it = g()
try:
raise RuntimeError
except RuntimeError:
next(it)
self.assertRaises(StopIteration, next, it)

def test_generator_finalizing_and_exc_info(self):
def test_generator_finalizing_and_sys_exception(self):
# See #7173
def simple_gen():
yield 1
Expand All @@ -996,7 +994,7 @@ def run_gen():
return next(gen)
run_gen()
gc_collect()
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def _check_generator_cleanup_exc_state(self, testfunc):
# Issue #12791: exception state is cleaned up as soon as a generator
Expand Down Expand Up @@ -1067,14 +1065,14 @@ def test_3114(self):
class MyObject:
def __del__(self):
nonlocal e
e = sys.exc_info()
e = sys.exception()
e = ()
try:
raise Exception(MyObject())
except:
pass
gc_collect() # For PyPy or other GCs.
self.assertEqual(e, (None, None, None))
self.assertIsNone(e)

def test_raise_does_not_create_context_chain_cycle(self):
class A(Exception):
Expand Down Expand Up @@ -1692,7 +1690,7 @@ def g():
raise ValueError
except ValueError:
yield 1
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())
yield 2

gen = g()
Expand Down
34 changes: 17 additions & 17 deletions Lib/test/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,16 +234,16 @@ class ExceptionTest(unittest.TestCase):
def test_except_throw(self):
def store_raise_exc_generator():
try:
self.assertEqual(sys.exc_info()[0], None)
self.assertIsNone(sys.exception())
yield
except Exception as exc:
# exception raised by gen.throw(exc)
self.assertEqual(sys.exc_info()[0], ValueError)
self.assertIsInstance(sys.exception(), ValueError)
self.assertIsNone(exc.__context__)
yield

# ensure that the exception is not lost
self.assertEqual(sys.exc_info()[0], ValueError)
self.assertIsInstance(sys.exception(), ValueError)
yield

# we should be able to raise back the ValueError
Expand All @@ -265,35 +265,35 @@ def store_raise_exc_generator():
next(make)
self.assertIsNone(cm.exception.__context__)

self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_except_next(self):
def gen():
self.assertEqual(sys.exc_info()[0], ValueError)
self.assertIsInstance(sys.exception(), ValueError)
yield "done"

g = gen()
try:
raise ValueError
except Exception:
self.assertEqual(next(g), "done")
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_except_gen_except(self):
def gen():
try:
self.assertEqual(sys.exc_info()[0], None)
self.assertIsNone(sys.exception())
yield
# we are called from "except ValueError:", TypeError must
# inherit ValueError in its context
raise TypeError()
except TypeError as exc:
self.assertEqual(sys.exc_info()[0], TypeError)
self.assertIsInstance(sys.exception(), TypeError)
self.assertEqual(type(exc.__context__), ValueError)
# here we are still called from the "except ValueError:"
self.assertEqual(sys.exc_info()[0], ValueError)
self.assertIsInstance(sys.exception(), ValueError)
yield
self.assertIsNone(sys.exc_info()[0])
self.assertIsNone(sys.exception())
yield "done"

g = gen()
Expand All @@ -304,7 +304,7 @@ def gen():
next(g)

self.assertEqual(next(g), "done")
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_nested_gen_except_loop(self):
def gen():
Expand All @@ -330,19 +330,19 @@ def test_except_throw_exception_context(self):
def gen():
try:
try:
self.assertEqual(sys.exc_info()[0], None)
self.assertIsNone(sys.exception())
yield
except ValueError:
# we are called from "except ValueError:"
self.assertEqual(sys.exc_info()[0], ValueError)
self.assertIsInstance(sys.exception(), ValueError)
raise TypeError()
except Exception as exc:
self.assertEqual(sys.exc_info()[0], TypeError)
self.assertIsInstance(sys.exception(), TypeError)
self.assertEqual(type(exc.__context__), ValueError)
# we are still called from "except ValueError:"
self.assertEqual(sys.exc_info()[0], ValueError)
self.assertIsInstance(sys.exception(), ValueError)
yield
self.assertIsNone(sys.exc_info()[0])
self.assertIsNone(sys.exception())
yield "done"

g = gen()
Expand All @@ -353,7 +353,7 @@ def gen():
g.throw(exc)

self.assertEqual(next(g), "done")
self.assertEqual(sys.exc_info(), (None, None, None))
self.assertIsNone(sys.exception())

def test_except_throw_bad_exception(self):
class E(Exception):
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -5097,8 +5097,7 @@ def test_encoding_errors_none(self):
message = []

def dummy_handle_error(record):
_, v, _ = sys.exc_info()
message.append(str(v))
message.append(str(sys.exception()))

handler.handleError = dummy_handle_error
logging.debug('The Øresund Bridge joins Copenhagen to Malmö')
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def main():
8 63.976 7.997 79.960 9.995 profilee.py:98(subhelper)"""
_ProfileOutput['print_callers'] = """\
:0(append) <- profilee.py:73(helper1)(4) 119.964
:0(exc_info) <- profilee.py:73(helper1)(4) 119.964
:0(exception) <- profilee.py:73(helper1)(4) 119.964
:0(hasattr) <- profilee.py:73(helper1)(4) 119.964
profilee.py:88(helper2)(8) 399.912
profilee.py:110(__getattr__) <- :0(hasattr)(12) 11.964
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def wrapper(*args, **kw):


def handle_error(prefix):
exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
exc_format = ' '.join(traceback.format_exception(sys.exception()))
if support.verbose:
sys.stdout.write(prefix + exc_format)

Expand Down
Loading