diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 1394a26f2096ff..6363211328f386 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2896,12 +2896,12 @@ def next(self): except Exception as e: try: import zlib + except ImportError: + pass + else: if isinstance(e, zlib.error): raise ReadError(f'zlib error: {e}') from None - else: - raise e - except ImportError: - raise e + raise break if tarinfo is not None: diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 192c948edc6056..cccc96eb6feb01 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -829,6 +829,27 @@ def test_zlib_error_does_not_leak(self): with self.assertRaises(tarfile.ReadError): tarfile.open(self.tarname) + def test_next_preserves_exception_traceback(self): + class ExpectedError(Exception): + pass + + class FailingFile(io.BytesIO): + def read(self, *args): + raise ExpectedError() + + with self.assertRaises(ExpectedError) as cm: + tarfile.open(fileobj=FailingFile(), mode="r:") + + next_frames = [] + tb = cm.exception.__traceback__ + while tb is not None: + code = tb.tb_frame.f_code + if (code.co_filename == tarfile.__file__ + and code.co_name == "next"): + next_frames.append(tb.tb_lineno) + tb = tb.tb_next + self.assertEqual(len(next_frames), 1) + def test_next_on_empty_tarfile(self): fd = io.BytesIO() tf = tarfile.open(fileobj=fd, mode="w")