From: Carsten Schoenert <c.schoenert@t-online.de>
Date: Mon, 17 Jan 2022 08:07:48 +0100
Subject: Test: Ignore test_failure.py file

This test file requires the library cython_test_exception_raiser which isn't
packaged yet.
---
 src/twisted/test/ignore_test_failure.py | 1035 +++++++++++++++++++++++++++++++
 src/twisted/test/test_failure.py        | 1035 -------------------------------
 2 files changed, 1035 insertions(+), 1035 deletions(-)
 create mode 100644 src/twisted/test/ignore_test_failure.py
 delete mode 100644 src/twisted/test/test_failure.py

diff --git a/src/twisted/test/ignore_test_failure.py b/src/twisted/test/ignore_test_failure.py
new file mode 100644
index 0000000..8b8e55b
--- /dev/null
+++ b/src/twisted/test/ignore_test_failure.py
@@ -0,0 +1,1035 @@
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Test cases for the L{twisted.python.failure} module.
+"""
+from __future__ import annotations
+
+import linecache
+import pdb
+import pickle
+import re
+import sys
+import traceback
+from dis import distb
+from io import StringIO
+from traceback import FrameSummary
+from types import TracebackType
+from typing import Any, Generator, cast
+from unittest import skipIf
+
+from cython_test_exception_raiser import raiser
+
+from twisted.python import failure, reflect
+from twisted.trial.unittest import SynchronousTestCase
+
+
+class ComparableException(Exception):
+    """An exception that can be compared by value."""
+
+    def __eq__(self, other: object) -> bool:
+        return (self.__class__ == other.__class__) and (
+            self.args == cast(ComparableException, other).args
+        )
+
+
+def getDivisionFailure(*, captureVars: bool = False) -> failure.Failure:
+    """
+    Make a C{Failure} of a divide-by-zero error.
+    """
+    if captureVars:
+        exampleLocalVar = "xyz"
+        # Silence the linter as this variable is checked via
+        # the traceback.
+        exampleLocalVar
+
+    try:
+        1 / 0
+    except BaseException:
+        f = failure.Failure(captureVars=captureVars)
+    return f
+
+
+class FailureTests(SynchronousTestCase):
+    """
+    Tests for L{failure.Failure}.
+    """
+
+    def test_failAndTrap(self) -> None:
+        """
+        Trapping a L{Failure}.
+        """
+        try:
+            raise NotImplementedError("test")
+        except BaseException:
+            f = failure.Failure()
+        error = f.trap(SystemExit, RuntimeError)
+        self.assertEqual(error, RuntimeError)
+        self.assertEqual(f.type, NotImplementedError)
+
+    def test_trapRaisesWrappedException(self) -> None:
+        """
+        If the wrapped C{Exception} is not a subclass of one of the
+        expected types, L{failure.Failure.trap} raises the wrapped
+        C{Exception}.
+        """
+        exception = ValueError()
+        try:
+            raise exception
+        except BaseException:
+            f = failure.Failure()
+
+        untrapped = self.assertRaises(ValueError, f.trap, OverflowError)
+        self.assertIs(exception, untrapped)
+
+    def test_failureValueFromFailure(self) -> None:
+        """
+        A L{failure.Failure} constructed from another
+        L{failure.Failure} instance, has its C{value} property set to
+        the value of that L{failure.Failure} instance.
+        """
+        exception = ValueError()
+        f1 = failure.Failure(exception)
+        f2 = failure.Failure(f1)
+        self.assertIs(f2.value, exception)
+
+    def test_failureValueFromFoundFailure(self) -> None:
+        """
+        A L{failure.Failure} constructed without a C{exc_value}
+        argument, will search for an "original" C{Failure}, and if
+        found, its value will be used as the value for the new
+        C{Failure}.
+        """
+        exception = ValueError()
+        f1 = failure.Failure(exception)
+        try:
+            f1.trap(OverflowError)
+        except BaseException:
+            f2 = failure.Failure()
+
+        self.assertIs(f2.value, exception)
+
+    def assertStartsWith(self, s: str, prefix: str) -> None:
+        """
+        Assert that C{s} starts with a particular C{prefix}.
+
+        @param s: The input string.
+        @type s: C{str}
+        @param prefix: The string that C{s} should start with.
+        @type prefix: C{str}
+        """
+        self.assertTrue(s.startswith(prefix), f"{prefix!r} is not the start of {s!r}")
+
+    def assertEndsWith(self, s: str, suffix: str) -> None:
+        """
+        Assert that C{s} end with a particular C{suffix}.
+
+        @param s: The input string.
+        @type s: C{str}
+        @param suffix: The string that C{s} should end with.
+        @type suffix: C{str}
+        """
+        self.assertTrue(s.endswith(suffix), f"{suffix!r} is not the end of {s!r}")
+
+    def assertTracebackFormat(self, tb: str, prefix: str, suffix: str) -> None:
+        """
+        Assert that the C{tb} traceback contains a particular C{prefix} and
+        C{suffix}.
+
+        @param tb: The traceback string.
+        @type tb: C{str}
+        @param prefix: The string that C{tb} should start with.
+        @type prefix: C{str}
+        @param suffix: The string that C{tb} should end with.
+        @type suffix: C{str}
+        """
+        self.assertStartsWith(tb, prefix)
+        self.assertEndsWith(tb, suffix)
+
+    def assertDetailedTraceback(
+        self, captureVars: bool = False, cleanFailure: bool = False
+    ) -> None:
+        """
+        Assert that L{printDetailedTraceback} produces and prints a detailed
+        traceback.
+
+        The detailed traceback consists of a header::
+
+          *--- Failure #20 ---
+
+        The body contains the stacktrace::
+
+          /twisted/test/test_failure.py:39: getDivisionFailure(...)
+
+        If C{captureVars} is enabled the body also includes a list of
+        globals and locals::
+
+           [ Locals ]
+             exampleLocalVar : 'xyz'
+             ...
+           ( Globals )
+             ...
+
+        Or when C{captureVars} is disabled::
+
+           [Capture of Locals and Globals disabled (use captureVars=True)]
+
+        When C{cleanFailure} is enabled references to other objects are removed
+        and replaced with strings.
+
+        And finally the footer with the L{Failure}'s value::
+
+          exceptions.ZeroDivisionError: float division
+          *--- End of Failure #20 ---
+
+        @param captureVars: Enables L{Failure.captureVars}.
+        @type captureVars: C{bool}
+        @param cleanFailure: Enables L{Failure.cleanFailure}.
+        @type cleanFailure: C{bool}
+        """
+        f = getDivisionFailure(captureVars=captureVars)
+        out = StringIO()
+        if cleanFailure:
+            f.cleanFailure()
+        f.printDetailedTraceback(out)
+
+        tb = out.getvalue()
+        start = "*--- Failure #%d%s---\n" % (
+            f.count,
+            (f.pickled and " (pickled) ") or " ",
+        )
+        end = "{}: {}\n*--- End of Failure #{} ---\n".format(
+            reflect.qual(f.type),
+            reflect.safe_str(f.value),
+            f.count,
+        )
+        self.assertTracebackFormat(tb, start, end)
+
+        # Variables are printed on lines with 2 leading spaces.
+        linesWithVars = [line for line in tb.splitlines() if line.startswith("  ")]
+
+        if captureVars:
+            self.assertNotEqual([], linesWithVars)
+            if cleanFailure:
+                line = "  exampleLocalVar : \"'xyz'\""
+            else:
+                line = "  exampleLocalVar : 'xyz'"
+            self.assertIn(line, linesWithVars)
+        else:
+            self.assertEqual([], linesWithVars)
+            self.assertIn(
+                " [Capture of Locals and Globals disabled (use " "captureVars=True)]\n",
+                tb,
+            )
+
+    def assertBriefTraceback(self, captureVars: bool = False) -> None:
+        """
+        Assert that L{printBriefTraceback} produces and prints a brief
+        traceback.
+
+        The brief traceback consists of a header::
+
+          Traceback: <type 'exceptions.ZeroDivisionError'>: float division
+
+        And the footer::
+
+          /twisted/test/test_failure.py:39:getDivisionFailure
+
+        @param captureVars: Enables L{Failure.captureVars}.
+        @type captureVars: C{bool}
+        """
+        if captureVars:
+            exampleLocalVar = "abcde"
+            # Silence the linter as this variable is checked via
+            # the traceback.
+            exampleLocalVar
+
+        f = getDivisionFailure()
+        out = StringIO()
+        f.printBriefTraceback(out)
+        tb = out.getvalue()
+        stack = ""
+        for method, filename, lineno, localVars, globalVars in f.frames:
+            stack += f"{filename}:{lineno}:{method}\n"
+
+        zde = repr(ZeroDivisionError)
+        self.assertTracebackFormat(
+            tb,
+            f"Traceback: {zde}: ",
+            f"{stack}",
+        )
+
+        if captureVars:
+            self.assertIsNone(re.search("exampleLocalVar.*abcde", tb))
+
+    def assertDefaultTraceback(self, captureVars: bool = False) -> None:
+        """
+        Assert that L{printTraceback} produces and prints a default traceback.
+
+        The default traceback consists of a header::
+
+          Traceback (most recent call last):
+
+        And the footer::
+
+            File "twisted/test/test_failure.py", line 39, in getDivisionFailure
+              1 / 0
+            exceptions.ZeroDivisionError: float division
+
+        @param captureVars: Enables L{Failure.captureVars}.
+        @type captureVars: C{bool}
+        """
+        if captureVars:
+            exampleLocalVar = "xyzzy"
+            # Silence the linter as this variable is checked via
+            # the traceback.
+            exampleLocalVar
+
+        f = getDivisionFailure(captureVars=captureVars)
+        out = StringIO()
+        f.printTraceback(out)
+        tb = out.getvalue()
+        stack = ""
+        for method, filename, lineno, localVars, globalVars in f.frames:
+            stack += f'  File "{filename}", line {lineno}, in {method}\n'
+            stack += f"    {linecache.getline(filename, lineno).strip()}\n"
+
+        self.assertTracebackFormat(
+            tb,
+            "Traceback (most recent call last):",
+            "%s%s: %s\n"
+            % (
+                stack,
+                reflect.qual(f.type),
+                reflect.safe_str(f.value),
+            ),
+        )
+
+        if captureVars:
+            self.assertIsNone(re.search("exampleLocalVar.*xyzzy", tb))
+
+    def test_printDetailedTraceback(self) -> None:
+        """
+        L{printDetailedTraceback} returns a detailed traceback including the
+        L{Failure}'s count.
+        """
+        self.assertDetailedTraceback()
+
+    def test_printBriefTraceback(self) -> None:
+        """
+        L{printBriefTraceback} returns a brief traceback.
+        """
+        self.assertBriefTraceback()
+
+    def test_printTraceback(self) -> None:
+        """
+        L{printTraceback} returns a traceback.
+        """
+        self.assertDefaultTraceback()
+
+    def test_printDetailedTracebackCapturedVars(self) -> None:
+        """
+        L{printDetailedTraceback} captures the locals and globals for its
+        stack frames and adds them to the traceback, when called on a
+        L{Failure} constructed with C{captureVars=True}.
+        """
+        self.assertDetailedTraceback(captureVars=True)
+
+    def test_printBriefTracebackCapturedVars(self) -> None:
+        """
+        L{printBriefTraceback} returns a brief traceback when called on a
+        L{Failure} constructed with C{captureVars=True}.
+
+        Local variables on the stack can not be seen in the resulting
+        traceback.
+        """
+        self.assertBriefTraceback(captureVars=True)
+
+    def test_printTracebackCapturedVars(self) -> None:
+        """
+        L{printTraceback} returns a traceback when called on a L{Failure}
+        constructed with C{captureVars=True}.
+
+        Local variables on the stack can not be seen in the resulting
+        traceback.
+        """
+        self.assertDefaultTraceback(captureVars=True)
+
+    def test_printDetailedTracebackCapturedVarsCleaned(self) -> None:
+        """
+        C{printDetailedTraceback} includes information about local variables on
+        the stack after C{cleanFailure} has been called.
+        """
+        self.assertDetailedTraceback(captureVars=True, cleanFailure=True)
+
+    def test_invalidFormatFramesDetail(self) -> None:
+        """
+        L{failure.format_frames} raises a L{ValueError} if the supplied
+        C{detail} level is unknown.
+        """
+        self.assertRaises(
+            ValueError, failure.format_frames, None, None, detail="noisia"
+        )
+
+    def test_ExplictPass(self) -> None:
+        e = RuntimeError()
+        f = failure.Failure(e)
+        f.trap(RuntimeError)
+        self.assertEqual(f.value, e)
+
+    def _getInnermostFrameLine(self, f: failure.Failure) -> str | None:
+        try:
+            f.raiseException()
+        except ZeroDivisionError:
+            tb = traceback.extract_tb(sys.exc_info()[2])
+            return tb[-1].line
+        else:
+            raise Exception("f.raiseException() didn't raise ZeroDivisionError!?")
+
+    def test_RaiseExceptionWithTB(self) -> None:
+        f = getDivisionFailure()
+        innerline = self._getInnermostFrameLine(f)
+        self.assertEqual(innerline, "1 / 0")
+
+    def test_ConstructionFails(self) -> None:
+        """
+        Creating a Failure with no arguments causes it to try to discover the
+        current interpreter exception state.  If no such state exists, creating
+        the Failure should raise a synchronous exception.
+        """
+        self.assertRaises(failure.NoCurrentExceptionError, failure.Failure)
+
+    def test_getTracebackObject(self) -> None:
+        """
+        If the C{Failure} has not been cleaned, then C{getTracebackObject}
+        returns the traceback object that captured in its constructor.
+        """
+        f = getDivisionFailure()
+        self.assertEqual(f.getTracebackObject(), f.tb)
+
+    def test_getTracebackObjectFromCaptureVars(self) -> None:
+        """
+        C{captureVars=True} has no effect on the result of
+        C{getTracebackObject}.
+        """
+        try:
+            1 / 0
+        except ZeroDivisionError:
+            noVarsFailure = failure.Failure()
+            varsFailure = failure.Failure(captureVars=True)
+        self.assertEqual(noVarsFailure.getTracebackObject(), varsFailure.tb)
+
+    def test_getTracebackObjectFromClean(self) -> None:
+        """
+        If the Failure has been cleaned, then C{getTracebackObject} returns an
+        object that looks the same to L{traceback.extract_tb}.
+        """
+        f = getDivisionFailure()
+        expected = traceback.extract_tb(f.getTracebackObject())
+        f.cleanFailure()
+        observed = traceback.extract_tb(f.getTracebackObject())
+        self.assertIsNotNone(expected)
+        self.assertEqual(expected, observed)
+
+    def test_getTracebackObjectFromCaptureVarsAndClean(self) -> None:
+        """
+        If the Failure was created with captureVars, then C{getTracebackObject}
+        returns an object that looks the same to L{traceback.extract_tb}.
+        """
+        f = getDivisionFailure(captureVars=True)
+        expected = traceback.extract_tb(f.getTracebackObject())
+        f.cleanFailure()
+        observed = traceback.extract_tb(f.getTracebackObject())
+        self.assertEqual(expected, observed)
+
+    def test_getTracebackObjectWithoutTraceback(self) -> None:
+        """
+        L{failure.Failure}s need not be constructed with traceback objects. If
+        a C{Failure} has no traceback information at all, C{getTracebackObject}
+        just returns None.
+
+        None is a good value, because traceback.extract_tb(None) -> [].
+        """
+        f = failure.Failure(Exception("some error"))
+        self.assertIsNone(f.getTracebackObject())
+
+    def test_tracebackFromExceptionInPython3(self) -> None:
+        """
+        If a L{failure.Failure} is constructed with an exception but no
+        traceback in Python 3, the traceback will be extracted from the
+        exception's C{__traceback__} attribute.
+        """
+        try:
+            1 / 0
+        except BaseException:
+            klass, exception, tb = sys.exc_info()
+        f = failure.Failure(exception)
+        self.assertIs(f.tb, tb)
+
+    def test_cleanFailureRemovesTracebackInPython3(self) -> None:
+        """
+        L{failure.Failure.cleanFailure} sets the C{__traceback__} attribute of
+        the exception to L{None} in Python 3.
+        """
+        f = getDivisionFailure()
+        self.assertIsNotNone(f.tb)
+        self.assertIs(f.value.__traceback__, f.tb)
+        f.cleanFailure()
+        self.assertIsNone(f.value.__traceback__)
+
+    def test_distb(self) -> None:
+        """
+        The traceback captured by a L{Failure} is compatible with the stdlib
+        L{dis.distb} function as used in post-mortem debuggers. Specifically,
+        it doesn't cause that function to raise an exception.
+        """
+        f = getDivisionFailure()
+        buf = StringIO()
+        distb(f.getTracebackObject(), file=buf)
+        # The bytecode details vary across Python versions, so we only check
+        # that the arrow pointing at the source of the exception is present.
+        self.assertIn(" --> ", buf.getvalue())
+
+    def test_repr(self) -> None:
+        """
+        The C{repr} of a L{failure.Failure} shows the type and string
+        representation of the underlying exception.
+        """
+        f = getDivisionFailure()
+        typeName = reflect.fullyQualifiedName(ZeroDivisionError)
+        self.assertEqual(
+            repr(f),
+            "<twisted.python.failure.Failure " "%s: division by zero>" % (typeName,),
+        )
+
+    def test_stackDeprecation(self) -> None:
+        """
+        C{Failure.stack} is gettable and settable, but depreacted.
+        """
+        f = getDivisionFailure()
+        f.stack = f.stack  # type: ignore[method-assign]
+        warnings = self.flushWarnings()
+        self.assertTrue(len(warnings) >= 1)
+        for w in warnings[-2:]:
+            self.assertEqual(
+                "twisted.python.failure.Failure.stack was deprecated in Twisted 24.10.0",
+                w["message"],
+            )
+
+    def test_failureWithoutTraceback(self) -> None:
+        """
+        C{Failure._withoutTraceback(exc)} gives the same result as
+        C{Failure(exc)}.
+        """
+        exc = ZeroDivisionError("hello")
+        dict1 = failure.Failure(exc).__dict__.copy()
+        failure2 = failure.Failure._withoutTraceback(exc)
+        self.assertIsInstance(failure2, failure.Failure)
+        dict2 = failure2.__dict__.copy()
+
+        # count increments with each new Failure constructed:
+        self.assertEqual(dict1.pop("count") + 1, dict2.pop("count"))
+
+        # The rest of the attributes should be identical:
+        self.assertEqual(dict1, dict2)
+
+    def test_failurePickling(self) -> None:
+        """
+        C{Failure(exc)} and C{Failure._withoutTraceback(exc)} can be pickled
+        and unpickled.
+        """
+        exc = ComparableException("hello")
+        failure1 = failure.Failure(exc)
+        self.assertPicklingRoundtrips(failure1)
+
+        # You would think this test is unnecessary, since it's just a
+        # C{Failure}, but actually the behavior of pickling can sometimes be
+        # different because of the way the constructor works!
+        failure2 = failure.Failure._withoutTraceback(exc)
+        self.assertPicklingRoundtrips(failure2)
+
+        # Here we test a Failure with a traceback:
+        try:
+            raise ComparableException("boo")
+        except BaseException:
+            failure3 = failure.Failure()
+        self.assertPicklingRoundtrips(failure3)
+
+    def assertPicklingRoundtrips(self, original_failure: failure.Failure) -> None:
+        """
+        The failure can be pickled and unpickled, and the C{parents} attribute
+        is included in the pickle.
+        """
+        failure2 = pickle.loads(pickle.dumps(original_failure))
+        expected = original_failure.__dict__.copy()
+        expected["pickled"] = 1
+        expected["tb"] = None
+        result = failure2.__dict__.copy()
+        self.assertEqual(expected, result)
+        self.assertEqual(failure2.frames, original_failure.frames)
+
+    def test_failurePicklingIncludesParents(self) -> None:
+        """
+        C{Failure.parents} is included in the pickle.
+        """
+        f = failure.Failure(ComparableException("hello"))
+        self.assertEqual(f.__getstate__()["parents"], f.parents)
+
+    def test_settableFrames(self) -> None:
+        """
+        C{Failure.frames} can be set, both before and after pickling.
+        """
+        original_failure = failure.Failure(getDivisionFailure())
+        original_failure.frames = original_failure.frames[:]
+        failure2 = pickle.loads(pickle.dumps(original_failure))
+        failure2.frames = failure2.frames[:-1]
+        self.assertEqual(failure2.frames, original_failure.frames[:-1])
+
+    def test_settableParents(self) -> None:
+        """
+        C{Failure.parents} can be set, both before and after pickling.
+
+        This is used by Foolscap.
+        """
+        original_failure = failure.Failure(ComparableException("hello"))
+        original_failure.parents = original_failure.parents[:]
+        failure2 = pickle.loads(pickle.dumps(original_failure))
+        failure2.parents = failure2.parents[:]
+
+
+class BrokenStr(Exception):
+    """
+    An exception class the instances of which cannot be presented as strings
+    via L{str}.
+    """
+
+    def __str__(self) -> str:
+        # Could raise something else, but there's no point as yet.
+        raise self
+
+
+class BrokenExceptionMetaclass(type):
+    """
+    A metaclass for an exception type which cannot be presented as a string via
+    L{str}.
+    """
+
+    def __str__(self) -> str:
+        raise ValueError("You cannot make a string out of me.")
+
+
+class BrokenExceptionType(Exception, metaclass=BrokenExceptionMetaclass):
+
+    """
+    The aforementioned exception type which cannot be presented as a string via
+    L{str}.
+    """
+
+
+class GetTracebackTests(SynchronousTestCase):
+    """
+    Tests for L{Failure.getTraceback}.
+    """
+
+    def _brokenValueTest(self, detail: str) -> None:
+        """
+        Construct a L{Failure} with an exception that raises an exception from
+        its C{__str__} method and then call C{getTraceback} with the specified
+        detail and verify that it returns a string.
+        """
+        x = BrokenStr()
+        f = failure.Failure(x)
+        traceback = f.getTraceback(detail=detail)
+        self.assertIsInstance(traceback, str)
+
+    def test_brokenValueBriefDetail(self) -> None:
+        """
+        A L{Failure} might wrap an exception with a C{__str__} method which
+        raises an exception.  In this case, calling C{getTraceback} on the
+        failure with the C{"brief"} detail does not raise an exception.
+        """
+        self._brokenValueTest("brief")
+
+    def test_brokenValueDefaultDetail(self) -> None:
+        """
+        Like test_brokenValueBriefDetail, but for the C{"default"} detail case.
+        """
+        self._brokenValueTest("default")
+
+    def test_brokenValueVerboseDetail(self) -> None:
+        """
+        Like test_brokenValueBriefDetail, but for the C{"default"} detail case.
+        """
+        self._brokenValueTest("verbose")
+
+    def _brokenTypeTest(self, detail: str) -> None:
+        """
+        Construct a L{Failure} with an exception type that raises an exception
+        from its C{__str__} method and then call C{getTraceback} with the
+        specified detail and verify that it returns a string.
+        """
+        f = failure.Failure(BrokenExceptionType())
+        traceback = f.getTraceback(detail=detail)
+        self.assertIsInstance(traceback, str)
+
+    def test_brokenTypeBriefDetail(self) -> None:
+        """
+                A L{Failure} might wrap an
+                newPublisher(evt)
+        xception the type object of which has a
+                C{__str__} method which raises an exception.  In this case, calling
+                C{getTraceback} on the failure with the C{"brief"} detail does not raise
+                an exception.
+        """
+        self._brokenTypeTest("brief")
+
+    def test_brokenTypeDefaultDetail(self) -> None:
+        """
+        Like test_brokenTypeBriefDetail, but for the C{"default"} detail case.
+        """
+        self._brokenTypeTest("default")
+
+    def test_brokenTypeVerboseDetail(self) -> None:
+        """
+        Like test_brokenTypeBriefDetail, but for the C{"verbose"} detail case.
+        """
+        self._brokenTypeTest("verbose")
+
+
+class FindFailureTests(SynchronousTestCase):
+    """
+    Tests for functionality related to identifying the C{Failure}.
+    """
+
+    @skipIf(raiser is None, "raiser extension not available")
+    def test_failureConstructionWithMungedStackSucceeds(self) -> None:
+        """
+        Pyrex and Cython are known to insert fake stack frames so as to give
+        more Python-like tracebacks. These stack frames with empty code objects
+        should not break extraction of the exception.
+        """
+        try:
+            raiser.raiseException()
+        except raiser.RaiserException:
+            f = failure.Failure()
+            self.assertTrue(f.check(raiser.RaiserException))
+        else:
+            self.fail("No exception raised from extension?!")
+
+
+# On Python 3.5, extract_tb returns "FrameSummary" objects, which are almost
+# like the old tuples. This being different does not affect the actual tests
+# as we are testing that the input works, and that extract_tb returns something
+# reasonable.
+def _tb(fn: str, lineno: int, name: str, text: None) -> FrameSummary:
+    return FrameSummary(fn, lineno, name)
+
+
+class FormattableTracebackTests(SynchronousTestCase):
+    """
+    Whitebox tests that show that L{failure._Traceback} constructs objects that
+    can be used by L{traceback.extract_tb}.
+
+    If the objects can be used by L{traceback.extract_tb}, then they can be
+    formatted using L{traceback.format_tb} and friends.
+    """
+
+    def test_singleFrame(self) -> None:
+        """
+        A C{_Traceback} object constructed with a single frame should be able
+        to be passed to L{traceback.extract_tb}, and we should get a singleton
+        list containing a (filename, lineno, methodname, line) tuple.
+        """
+        tb = failure._Traceback([["method", "filename.py", 123, {}, {}]])
+        # Note that we don't need to test that extract_tb correctly extracts
+        # the line's contents. In this case, since filename.py doesn't exist,
+        # it will just use None.
+        self.assertEqual(
+            traceback.extract_tb(tb), [_tb("filename.py", 123, "method", None)]
+        )
+
+    def test_manyFrames(self) -> None:
+        """
+        A C{_Traceback} object constructed with multiple frames should be able
+        to be passed to L{traceback.extract_tb}, and we should get a list
+        containing a tuple for each frame.
+        """
+        tb = failure._Traceback(
+            [
+                ["method1", "filename.py", 123, {}, {}],
+                ["method2", "filename.py", 235, {}, {}],
+            ],
+        )
+        self.assertEqual(
+            traceback.extract_tb(tb),
+            [
+                _tb("filename.py", 123, "method1", None),
+                _tb("filename.py", 235, "method2", None),
+            ],
+        )
+
+        # We should also be able to extract_stack on it
+        self.assertEqual(
+            traceback.extract_stack(tb.tb_frame),
+            [
+                _tb("filename.py", 123, "method1", None),
+            ],
+        )
+
+
+class FakeAttributesTests(SynchronousTestCase):
+    """
+    _Frame, _Code and _TracebackFrame objects should possess some basic
+    attributes that qualify them as fake python objects, allowing the return of
+    _Traceback to be used as a fake traceback. The attributes that have zero or
+    empty values are there so that things expecting them find them (e.g. post
+    mortem debuggers).
+    """
+
+    def test_fakeFrameAttributes(self) -> None:
+        """
+        L{_Frame} instances have the C{f_globals} and C{f_locals} attributes
+        bound to C{dict} instance.  They also have the C{f_code} attribute
+        bound to something like a code object.
+        """
+        back_frame = failure._Frame(
+            (
+                "dummyparent",
+                "dummyparentfile",
+                111,
+                None,
+                None,
+            ),
+            None,
+        )
+        fake_locals = {"local_var": 42}
+        fake_globals = {"global_var": 100}
+        frame = failure._Frame(
+            (
+                "dummyname",
+                "dummyfilename",
+                42,
+                fake_locals,
+                fake_globals,
+            ),
+            back_frame,
+        )
+        self.assertEqual(frame.f_globals, fake_globals)
+        self.assertEqual(frame.f_locals, fake_locals)
+        self.assertIsInstance(frame.f_code, failure._Code)
+        self.assertEqual(frame.f_back, back_frame)
+        self.assertIsInstance(frame.f_builtins, dict)
+        self.assertIsInstance(frame.f_lasti, int)
+        self.assertEqual(frame.f_lineno, 42)
+        self.assertIsInstance(frame.f_trace, type(None))
+
+    def test_fakeCodeAttributes(self) -> None:
+        """
+        See L{FakeAttributesTests} for more details about this test.
+        """
+        code = failure._Code("dummyname", "dummyfilename")
+        self.assertEqual(code.co_name, "dummyname")
+        self.assertEqual(code.co_filename, "dummyfilename")
+        self.assertIsInstance(code.co_argcount, int)
+        self.assertIsInstance(code.co_code, bytes)
+        self.assertIsInstance(code.co_cellvars, tuple)
+        self.assertIsInstance(code.co_consts, tuple)
+        self.assertIsInstance(code.co_firstlineno, int)
+        self.assertIsInstance(code.co_flags, int)
+        self.assertIsInstance(code.co_lnotab, bytes)
+        self.assertIsInstance(code.co_freevars, tuple)
+        self.assertIsInstance(code.co_posonlyargcount, int)
+        self.assertIsInstance(code.co_kwonlyargcount, int)
+        self.assertIsInstance(code.co_names, tuple)
+        self.assertIsInstance(code.co_nlocals, int)
+        self.assertIsInstance(code.co_stacksize, int)
+        self.assertIsInstance(code.co_varnames, list)
+        self.assertIsInstance(code.co_positions(), tuple)
+
+    def test_fakeTracebackFrame(self) -> None:
+        """
+        See L{FakeAttributesTests} for more details about this test.
+        """
+        frame = failure._Frame(
+            ("dummyname", "dummyfilename", 42, {}, {}),
+            None,
+        )
+        traceback_frame = failure._TracebackFrame(frame)
+        self.assertEqual(traceback_frame.tb_frame, frame)
+        self.assertEqual(traceback_frame.tb_lineno, 42)
+        self.assertIsInstance(traceback_frame.tb_lasti, int)
+        self.assertTrue(hasattr(traceback_frame, "tb_next"))
+
+
+class DebugModeTests(SynchronousTestCase):
+    """
+    Failure's debug mode should allow jumping into the debugger.
+    """
+
+    def setUp(self) -> None:
+        """
+        Override pdb.post_mortem so we can make sure it's called.
+        """
+        # Make sure any changes we make are reversed:
+        post_mortem = pdb.post_mortem
+        origInit = failure.Failure.__init__
+
+        def restore() -> None:
+            pdb.post_mortem = post_mortem
+            failure.Failure.__init__ = origInit  # type: ignore[method-assign]
+
+        self.addCleanup(restore)
+
+        self.result: list[TracebackType | None] = []
+
+        def logging_post_mortem(t: TracebackType | None = None) -> None:
+            self.result.append(t)
+
+        pdb.post_mortem = logging_post_mortem
+        failure.startDebugMode()
+
+    def test_regularFailure(self) -> None:
+        """
+        If startDebugMode() is called, calling Failure() will first call
+        pdb.post_mortem with the traceback.
+        """
+        try:
+            1 / 0
+        except BaseException:
+            typ, exc, tb = sys.exc_info()
+            f = failure.Failure()
+        self.assertEqual(self.result, [tb])
+        self.assertFalse(f.captureVars)
+
+    def test_captureVars(self) -> None:
+        """
+        If startDebugMode() is called, passing captureVars to Failure() will
+        not blow up.
+        """
+        try:
+            1 / 0
+        except BaseException:
+            typ, exc, tb = sys.exc_info()
+            f = failure.Failure(captureVars=True)
+        self.assertEqual(self.result, [tb])
+        self.assertTrue(f.captureVars)
+
+
+class ExtendedGeneratorTests(SynchronousTestCase):
+    """
+    Tests C{failure.Failure} support for generator features added in Python 2.5
+    """
+
+    def _throwIntoGenerator(
+        self, f: failure.Failure, g: Generator[Any, Any, Any]
+    ) -> None:
+        try:
+            f.throwExceptionIntoGenerator(g)
+        except StopIteration:
+            pass
+        else:
+            self.fail("throwExceptionIntoGenerator should have raised " "StopIteration")
+
+    def test_throwExceptionIntoGenerator(self) -> None:
+        """
+        It should be possible to throw the exception that a Failure
+        represents into a generator.
+        """
+        stuff = []
+
+        def generator() -> Generator[None, None, None]:
+            try:
+                yield
+            except BaseException:
+                stuff.append(sys.exc_info())
+            else:
+                self.fail("Yield should have yielded exception.")
+
+        g = generator()
+        f = getDivisionFailure()
+        next(g)
+        self._throwIntoGenerator(f, g)
+
+        self.assertEqual(stuff[0][0], ZeroDivisionError)
+        self.assertIsInstance(stuff[0][1], ZeroDivisionError)
+
+        self.assertEqual(traceback.extract_tb(stuff[0][2])[-1][-1], "1 / 0")
+
+    def test_failureConstructionFindsOriginalFailure(self) -> None:
+        """
+        When a Failure is constructed in the context of an exception
+        handler that is handling an exception raised by
+        throwExceptionIntoGenerator, the new Failure should be chained to that
+        original Failure.
+        """
+        f = getDivisionFailure()
+        f.cleanFailure()
+        original_failure_str = f.getTraceback()
+
+        newFailures = []
+
+        def generator() -> Generator[None, None, None]:
+            try:
+                yield
+            except BaseException:
+                newFailures.append(failure.Failure())
+            else:
+                self.fail("No exception sent to generator")
+
+        g = generator()
+        next(g)
+        self._throwIntoGenerator(f, g)
+
+        self.assertEqual(len(newFailures), 1)
+
+        # The original failure should not be changed.
+        self.assertEqual(original_failure_str, f.getTraceback())
+
+        # The new failure should be different and contain stack info for
+        # our generator.
+        self.assertNotEqual(newFailures[0].getTraceback(), f.getTraceback())
+        self.assertIn("generator", newFailures[0].getTraceback())
+        self.assertNotIn("generator", f.getTraceback())
+
+    def test_ambiguousFailureInGenerator(self) -> None:
+        """
+        When a generator reraises a different exception, creating a L{Failure}
+        inside the generator should find the reraised exception rather than
+        original one.
+        """
+
+        def generator() -> Generator[None, None, None]:
+            try:
+                try:
+                    yield
+                except BaseException:
+                    [][1]
+            except BaseException:
+                self.assertIsInstance(failure.Failure().value, IndexError)
+
+        g = generator()
+        next(g)
+        f = getDivisionFailure()
+        self._throwIntoGenerator(f, g)
+
+    def test_ambiguousFailureFromGenerator(self) -> None:
+        """
+        When a generator reraises a different exception, creating a L{Failure}
+        above the generator should find the reraised exception rather than
+        original one.
+        """
+
+        def generator() -> Generator[None, None, None]:
+            try:
+                yield
+            except BaseException:
+                [][1]
+
+        g = generator()
+        next(g)
+        f = getDivisionFailure()
+        try:
+            self._throwIntoGenerator(f, g)
+        except BaseException:
+            self.assertIsInstance(failure.Failure().value, IndexError)
diff --git a/src/twisted/test/test_failure.py b/src/twisted/test/test_failure.py
deleted file mode 100644
index 8b8e55b..0000000
--- a/src/twisted/test/test_failure.py
+++ /dev/null
@@ -1,1035 +0,0 @@
-# Copyright (c) Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Test cases for the L{twisted.python.failure} module.
-"""
-from __future__ import annotations
-
-import linecache
-import pdb
-import pickle
-import re
-import sys
-import traceback
-from dis import distb
-from io import StringIO
-from traceback import FrameSummary
-from types import TracebackType
-from typing import Any, Generator, cast
-from unittest import skipIf
-
-from cython_test_exception_raiser import raiser
-
-from twisted.python import failure, reflect
-from twisted.trial.unittest import SynchronousTestCase
-
-
-class ComparableException(Exception):
-    """An exception that can be compared by value."""
-
-    def __eq__(self, other: object) -> bool:
-        return (self.__class__ == other.__class__) and (
-            self.args == cast(ComparableException, other).args
-        )
-
-
-def getDivisionFailure(*, captureVars: bool = False) -> failure.Failure:
-    """
-    Make a C{Failure} of a divide-by-zero error.
-    """
-    if captureVars:
-        exampleLocalVar = "xyz"
-        # Silence the linter as this variable is checked via
-        # the traceback.
-        exampleLocalVar
-
-    try:
-        1 / 0
-    except BaseException:
-        f = failure.Failure(captureVars=captureVars)
-    return f
-
-
-class FailureTests(SynchronousTestCase):
-    """
-    Tests for L{failure.Failure}.
-    """
-
-    def test_failAndTrap(self) -> None:
-        """
-        Trapping a L{Failure}.
-        """
-        try:
-            raise NotImplementedError("test")
-        except BaseException:
-            f = failure.Failure()
-        error = f.trap(SystemExit, RuntimeError)
-        self.assertEqual(error, RuntimeError)
-        self.assertEqual(f.type, NotImplementedError)
-
-    def test_trapRaisesWrappedException(self) -> None:
-        """
-        If the wrapped C{Exception} is not a subclass of one of the
-        expected types, L{failure.Failure.trap} raises the wrapped
-        C{Exception}.
-        """
-        exception = ValueError()
-        try:
-            raise exception
-        except BaseException:
-            f = failure.Failure()
-
-        untrapped = self.assertRaises(ValueError, f.trap, OverflowError)
-        self.assertIs(exception, untrapped)
-
-    def test_failureValueFromFailure(self) -> None:
-        """
-        A L{failure.Failure} constructed from another
-        L{failure.Failure} instance, has its C{value} property set to
-        the value of that L{failure.Failure} instance.
-        """
-        exception = ValueError()
-        f1 = failure.Failure(exception)
-        f2 = failure.Failure(f1)
-        self.assertIs(f2.value, exception)
-
-    def test_failureValueFromFoundFailure(self) -> None:
-        """
-        A L{failure.Failure} constructed without a C{exc_value}
-        argument, will search for an "original" C{Failure}, and if
-        found, its value will be used as the value for the new
-        C{Failure}.
-        """
-        exception = ValueError()
-        f1 = failure.Failure(exception)
-        try:
-            f1.trap(OverflowError)
-        except BaseException:
-            f2 = failure.Failure()
-
-        self.assertIs(f2.value, exception)
-
-    def assertStartsWith(self, s: str, prefix: str) -> None:
-        """
-        Assert that C{s} starts with a particular C{prefix}.
-
-        @param s: The input string.
-        @type s: C{str}
-        @param prefix: The string that C{s} should start with.
-        @type prefix: C{str}
-        """
-        self.assertTrue(s.startswith(prefix), f"{prefix!r} is not the start of {s!r}")
-
-    def assertEndsWith(self, s: str, suffix: str) -> None:
-        """
-        Assert that C{s} end with a particular C{suffix}.
-
-        @param s: The input string.
-        @type s: C{str}
-        @param suffix: The string that C{s} should end with.
-        @type suffix: C{str}
-        """
-        self.assertTrue(s.endswith(suffix), f"{suffix!r} is not the end of {s!r}")
-
-    def assertTracebackFormat(self, tb: str, prefix: str, suffix: str) -> None:
-        """
-        Assert that the C{tb} traceback contains a particular C{prefix} and
-        C{suffix}.
-
-        @param tb: The traceback string.
-        @type tb: C{str}
-        @param prefix: The string that C{tb} should start with.
-        @type prefix: C{str}
-        @param suffix: The string that C{tb} should end with.
-        @type suffix: C{str}
-        """
-        self.assertStartsWith(tb, prefix)
-        self.assertEndsWith(tb, suffix)
-
-    def assertDetailedTraceback(
-        self, captureVars: bool = False, cleanFailure: bool = False
-    ) -> None:
-        """
-        Assert that L{printDetailedTraceback} produces and prints a detailed
-        traceback.
-
-        The detailed traceback consists of a header::
-
-          *--- Failure #20 ---
-
-        The body contains the stacktrace::
-
-          /twisted/test/test_failure.py:39: getDivisionFailure(...)
-
-        If C{captureVars} is enabled the body also includes a list of
-        globals and locals::
-
-           [ Locals ]
-             exampleLocalVar : 'xyz'
-             ...
-           ( Globals )
-             ...
-
-        Or when C{captureVars} is disabled::
-
-           [Capture of Locals and Globals disabled (use captureVars=True)]
-
-        When C{cleanFailure} is enabled references to other objects are removed
-        and replaced with strings.
-
-        And finally the footer with the L{Failure}'s value::
-
-          exceptions.ZeroDivisionError: float division
-          *--- End of Failure #20 ---
-
-        @param captureVars: Enables L{Failure.captureVars}.
-        @type captureVars: C{bool}
-        @param cleanFailure: Enables L{Failure.cleanFailure}.
-        @type cleanFailure: C{bool}
-        """
-        f = getDivisionFailure(captureVars=captureVars)
-        out = StringIO()
-        if cleanFailure:
-            f.cleanFailure()
-        f.printDetailedTraceback(out)
-
-        tb = out.getvalue()
-        start = "*--- Failure #%d%s---\n" % (
-            f.count,
-            (f.pickled and " (pickled) ") or " ",
-        )
-        end = "{}: {}\n*--- End of Failure #{} ---\n".format(
-            reflect.qual(f.type),
-            reflect.safe_str(f.value),
-            f.count,
-        )
-        self.assertTracebackFormat(tb, start, end)
-
-        # Variables are printed on lines with 2 leading spaces.
-        linesWithVars = [line for line in tb.splitlines() if line.startswith("  ")]
-
-        if captureVars:
-            self.assertNotEqual([], linesWithVars)
-            if cleanFailure:
-                line = "  exampleLocalVar : \"'xyz'\""
-            else:
-                line = "  exampleLocalVar : 'xyz'"
-            self.assertIn(line, linesWithVars)
-        else:
-            self.assertEqual([], linesWithVars)
-            self.assertIn(
-                " [Capture of Locals and Globals disabled (use " "captureVars=True)]\n",
-                tb,
-            )
-
-    def assertBriefTraceback(self, captureVars: bool = False) -> None:
-        """
-        Assert that L{printBriefTraceback} produces and prints a brief
-        traceback.
-
-        The brief traceback consists of a header::
-
-          Traceback: <type 'exceptions.ZeroDivisionError'>: float division
-
-        And the footer::
-
-          /twisted/test/test_failure.py:39:getDivisionFailure
-
-        @param captureVars: Enables L{Failure.captureVars}.
-        @type captureVars: C{bool}
-        """
-        if captureVars:
-            exampleLocalVar = "abcde"
-            # Silence the linter as this variable is checked via
-            # the traceback.
-            exampleLocalVar
-
-        f = getDivisionFailure()
-        out = StringIO()
-        f.printBriefTraceback(out)
-        tb = out.getvalue()
-        stack = ""
-        for method, filename, lineno, localVars, globalVars in f.frames:
-            stack += f"{filename}:{lineno}:{method}\n"
-
-        zde = repr(ZeroDivisionError)
-        self.assertTracebackFormat(
-            tb,
-            f"Traceback: {zde}: ",
-            f"{stack}",
-        )
-
-        if captureVars:
-            self.assertIsNone(re.search("exampleLocalVar.*abcde", tb))
-
-    def assertDefaultTraceback(self, captureVars: bool = False) -> None:
-        """
-        Assert that L{printTraceback} produces and prints a default traceback.
-
-        The default traceback consists of a header::
-
-          Traceback (most recent call last):
-
-        And the footer::
-
-            File "twisted/test/test_failure.py", line 39, in getDivisionFailure
-              1 / 0
-            exceptions.ZeroDivisionError: float division
-
-        @param captureVars: Enables L{Failure.captureVars}.
-        @type captureVars: C{bool}
-        """
-        if captureVars:
-            exampleLocalVar = "xyzzy"
-            # Silence the linter as this variable is checked via
-            # the traceback.
-            exampleLocalVar
-
-        f = getDivisionFailure(captureVars=captureVars)
-        out = StringIO()
-        f.printTraceback(out)
-        tb = out.getvalue()
-        stack = ""
-        for method, filename, lineno, localVars, globalVars in f.frames:
-            stack += f'  File "{filename}", line {lineno}, in {method}\n'
-            stack += f"    {linecache.getline(filename, lineno).strip()}\n"
-
-        self.assertTracebackFormat(
-            tb,
-            "Traceback (most recent call last):",
-            "%s%s: %s\n"
-            % (
-                stack,
-                reflect.qual(f.type),
-                reflect.safe_str(f.value),
-            ),
-        )
-
-        if captureVars:
-            self.assertIsNone(re.search("exampleLocalVar.*xyzzy", tb))
-
-    def test_printDetailedTraceback(self) -> None:
-        """
-        L{printDetailedTraceback} returns a detailed traceback including the
-        L{Failure}'s count.
-        """
-        self.assertDetailedTraceback()
-
-    def test_printBriefTraceback(self) -> None:
-        """
-        L{printBriefTraceback} returns a brief traceback.
-        """
-        self.assertBriefTraceback()
-
-    def test_printTraceback(self) -> None:
-        """
-        L{printTraceback} returns a traceback.
-        """
-        self.assertDefaultTraceback()
-
-    def test_printDetailedTracebackCapturedVars(self) -> None:
-        """
-        L{printDetailedTraceback} captures the locals and globals for its
-        stack frames and adds them to the traceback, when called on a
-        L{Failure} constructed with C{captureVars=True}.
-        """
-        self.assertDetailedTraceback(captureVars=True)
-
-    def test_printBriefTracebackCapturedVars(self) -> None:
-        """
-        L{printBriefTraceback} returns a brief traceback when called on a
-        L{Failure} constructed with C{captureVars=True}.
-
-        Local variables on the stack can not be seen in the resulting
-        traceback.
-        """
-        self.assertBriefTraceback(captureVars=True)
-
-    def test_printTracebackCapturedVars(self) -> None:
-        """
-        L{printTraceback} returns a traceback when called on a L{Failure}
-        constructed with C{captureVars=True}.
-
-        Local variables on the stack can not be seen in the resulting
-        traceback.
-        """
-        self.assertDefaultTraceback(captureVars=True)
-
-    def test_printDetailedTracebackCapturedVarsCleaned(self) -> None:
-        """
-        C{printDetailedTraceback} includes information about local variables on
-        the stack after C{cleanFailure} has been called.
-        """
-        self.assertDetailedTraceback(captureVars=True, cleanFailure=True)
-
-    def test_invalidFormatFramesDetail(self) -> None:
-        """
-        L{failure.format_frames} raises a L{ValueError} if the supplied
-        C{detail} level is unknown.
-        """
-        self.assertRaises(
-            ValueError, failure.format_frames, None, None, detail="noisia"
-        )
-
-    def test_ExplictPass(self) -> None:
-        e = RuntimeError()
-        f = failure.Failure(e)
-        f.trap(RuntimeError)
-        self.assertEqual(f.value, e)
-
-    def _getInnermostFrameLine(self, f: failure.Failure) -> str | None:
-        try:
-            f.raiseException()
-        except ZeroDivisionError:
-            tb = traceback.extract_tb(sys.exc_info()[2])
-            return tb[-1].line
-        else:
-            raise Exception("f.raiseException() didn't raise ZeroDivisionError!?")
-
-    def test_RaiseExceptionWithTB(self) -> None:
-        f = getDivisionFailure()
-        innerline = self._getInnermostFrameLine(f)
-        self.assertEqual(innerline, "1 / 0")
-
-    def test_ConstructionFails(self) -> None:
-        """
-        Creating a Failure with no arguments causes it to try to discover the
-        current interpreter exception state.  If no such state exists, creating
-        the Failure should raise a synchronous exception.
-        """
-        self.assertRaises(failure.NoCurrentExceptionError, failure.Failure)
-
-    def test_getTracebackObject(self) -> None:
-        """
-        If the C{Failure} has not been cleaned, then C{getTracebackObject}
-        returns the traceback object that captured in its constructor.
-        """
-        f = getDivisionFailure()
-        self.assertEqual(f.getTracebackObject(), f.tb)
-
-    def test_getTracebackObjectFromCaptureVars(self) -> None:
-        """
-        C{captureVars=True} has no effect on the result of
-        C{getTracebackObject}.
-        """
-        try:
-            1 / 0
-        except ZeroDivisionError:
-            noVarsFailure = failure.Failure()
-            varsFailure = failure.Failure(captureVars=True)
-        self.assertEqual(noVarsFailure.getTracebackObject(), varsFailure.tb)
-
-    def test_getTracebackObjectFromClean(self) -> None:
-        """
-        If the Failure has been cleaned, then C{getTracebackObject} returns an
-        object that looks the same to L{traceback.extract_tb}.
-        """
-        f = getDivisionFailure()
-        expected = traceback.extract_tb(f.getTracebackObject())
-        f.cleanFailure()
-        observed = traceback.extract_tb(f.getTracebackObject())
-        self.assertIsNotNone(expected)
-        self.assertEqual(expected, observed)
-
-    def test_getTracebackObjectFromCaptureVarsAndClean(self) -> None:
-        """
-        If the Failure was created with captureVars, then C{getTracebackObject}
-        returns an object that looks the same to L{traceback.extract_tb}.
-        """
-        f = getDivisionFailure(captureVars=True)
-        expected = traceback.extract_tb(f.getTracebackObject())
-        f.cleanFailure()
-        observed = traceback.extract_tb(f.getTracebackObject())
-        self.assertEqual(expected, observed)
-
-    def test_getTracebackObjectWithoutTraceback(self) -> None:
-        """
-        L{failure.Failure}s need not be constructed with traceback objects. If
-        a C{Failure} has no traceback information at all, C{getTracebackObject}
-        just returns None.
-
-        None is a good value, because traceback.extract_tb(None) -> [].
-        """
-        f = failure.Failure(Exception("some error"))
-        self.assertIsNone(f.getTracebackObject())
-
-    def test_tracebackFromExceptionInPython3(self) -> None:
-        """
-        If a L{failure.Failure} is constructed with an exception but no
-        traceback in Python 3, the traceback will be extracted from the
-        exception's C{__traceback__} attribute.
-        """
-        try:
-            1 / 0
-        except BaseException:
-            klass, exception, tb = sys.exc_info()
-        f = failure.Failure(exception)
-        self.assertIs(f.tb, tb)
-
-    def test_cleanFailureRemovesTracebackInPython3(self) -> None:
-        """
-        L{failure.Failure.cleanFailure} sets the C{__traceback__} attribute of
-        the exception to L{None} in Python 3.
-        """
-        f = getDivisionFailure()
-        self.assertIsNotNone(f.tb)
-        self.assertIs(f.value.__traceback__, f.tb)
-        f.cleanFailure()
-        self.assertIsNone(f.value.__traceback__)
-
-    def test_distb(self) -> None:
-        """
-        The traceback captured by a L{Failure} is compatible with the stdlib
-        L{dis.distb} function as used in post-mortem debuggers. Specifically,
-        it doesn't cause that function to raise an exception.
-        """
-        f = getDivisionFailure()
-        buf = StringIO()
-        distb(f.getTracebackObject(), file=buf)
-        # The bytecode details vary across Python versions, so we only check
-        # that the arrow pointing at the source of the exception is present.
-        self.assertIn(" --> ", buf.getvalue())
-
-    def test_repr(self) -> None:
-        """
-        The C{repr} of a L{failure.Failure} shows the type and string
-        representation of the underlying exception.
-        """
-        f = getDivisionFailure()
-        typeName = reflect.fullyQualifiedName(ZeroDivisionError)
-        self.assertEqual(
-            repr(f),
-            "<twisted.python.failure.Failure " "%s: division by zero>" % (typeName,),
-        )
-
-    def test_stackDeprecation(self) -> None:
-        """
-        C{Failure.stack} is gettable and settable, but depreacted.
-        """
-        f = getDivisionFailure()
-        f.stack = f.stack  # type: ignore[method-assign]
-        warnings = self.flushWarnings()
-        self.assertTrue(len(warnings) >= 1)
-        for w in warnings[-2:]:
-            self.assertEqual(
-                "twisted.python.failure.Failure.stack was deprecated in Twisted 24.10.0",
-                w["message"],
-            )
-
-    def test_failureWithoutTraceback(self) -> None:
-        """
-        C{Failure._withoutTraceback(exc)} gives the same result as
-        C{Failure(exc)}.
-        """
-        exc = ZeroDivisionError("hello")
-        dict1 = failure.Failure(exc).__dict__.copy()
-        failure2 = failure.Failure._withoutTraceback(exc)
-        self.assertIsInstance(failure2, failure.Failure)
-        dict2 = failure2.__dict__.copy()
-
-        # count increments with each new Failure constructed:
-        self.assertEqual(dict1.pop("count") + 1, dict2.pop("count"))
-
-        # The rest of the attributes should be identical:
-        self.assertEqual(dict1, dict2)
-
-    def test_failurePickling(self) -> None:
-        """
-        C{Failure(exc)} and C{Failure._withoutTraceback(exc)} can be pickled
-        and unpickled.
-        """
-        exc = ComparableException("hello")
-        failure1 = failure.Failure(exc)
-        self.assertPicklingRoundtrips(failure1)
-
-        # You would think this test is unnecessary, since it's just a
-        # C{Failure}, but actually the behavior of pickling can sometimes be
-        # different because of the way the constructor works!
-        failure2 = failure.Failure._withoutTraceback(exc)
-        self.assertPicklingRoundtrips(failure2)
-
-        # Here we test a Failure with a traceback:
-        try:
-            raise ComparableException("boo")
-        except BaseException:
-            failure3 = failure.Failure()
-        self.assertPicklingRoundtrips(failure3)
-
-    def assertPicklingRoundtrips(self, original_failure: failure.Failure) -> None:
-        """
-        The failure can be pickled and unpickled, and the C{parents} attribute
-        is included in the pickle.
-        """
-        failure2 = pickle.loads(pickle.dumps(original_failure))
-        expected = original_failure.__dict__.copy()
-        expected["pickled"] = 1
-        expected["tb"] = None
-        result = failure2.__dict__.copy()
-        self.assertEqual(expected, result)
-        self.assertEqual(failure2.frames, original_failure.frames)
-
-    def test_failurePicklingIncludesParents(self) -> None:
-        """
-        C{Failure.parents} is included in the pickle.
-        """
-        f = failure.Failure(ComparableException("hello"))
-        self.assertEqual(f.__getstate__()["parents"], f.parents)
-
-    def test_settableFrames(self) -> None:
-        """
-        C{Failure.frames} can be set, both before and after pickling.
-        """
-        original_failure = failure.Failure(getDivisionFailure())
-        original_failure.frames = original_failure.frames[:]
-        failure2 = pickle.loads(pickle.dumps(original_failure))
-        failure2.frames = failure2.frames[:-1]
-        self.assertEqual(failure2.frames, original_failure.frames[:-1])
-
-    def test_settableParents(self) -> None:
-        """
-        C{Failure.parents} can be set, both before and after pickling.
-
-        This is used by Foolscap.
-        """
-        original_failure = failure.Failure(ComparableException("hello"))
-        original_failure.parents = original_failure.parents[:]
-        failure2 = pickle.loads(pickle.dumps(original_failure))
-        failure2.parents = failure2.parents[:]
-
-
-class BrokenStr(Exception):
-    """
-    An exception class the instances of which cannot be presented as strings
-    via L{str}.
-    """
-
-    def __str__(self) -> str:
-        # Could raise something else, but there's no point as yet.
-        raise self
-
-
-class BrokenExceptionMetaclass(type):
-    """
-    A metaclass for an exception type which cannot be presented as a string via
-    L{str}.
-    """
-
-    def __str__(self) -> str:
-        raise ValueError("You cannot make a string out of me.")
-
-
-class BrokenExceptionType(Exception, metaclass=BrokenExceptionMetaclass):
-
-    """
-    The aforementioned exception type which cannot be presented as a string via
-    L{str}.
-    """
-
-
-class GetTracebackTests(SynchronousTestCase):
-    """
-    Tests for L{Failure.getTraceback}.
-    """
-
-    def _brokenValueTest(self, detail: str) -> None:
-        """
-        Construct a L{Failure} with an exception that raises an exception from
-        its C{__str__} method and then call C{getTraceback} with the specified
-        detail and verify that it returns a string.
-        """
-        x = BrokenStr()
-        f = failure.Failure(x)
-        traceback = f.getTraceback(detail=detail)
-        self.assertIsInstance(traceback, str)
-
-    def test_brokenValueBriefDetail(self) -> None:
-        """
-        A L{Failure} might wrap an exception with a C{__str__} method which
-        raises an exception.  In this case, calling C{getTraceback} on the
-        failure with the C{"brief"} detail does not raise an exception.
-        """
-        self._brokenValueTest("brief")
-
-    def test_brokenValueDefaultDetail(self) -> None:
-        """
-        Like test_brokenValueBriefDetail, but for the C{"default"} detail case.
-        """
-        self._brokenValueTest("default")
-
-    def test_brokenValueVerboseDetail(self) -> None:
-        """
-        Like test_brokenValueBriefDetail, but for the C{"default"} detail case.
-        """
-        self._brokenValueTest("verbose")
-
-    def _brokenTypeTest(self, detail: str) -> None:
-        """
-        Construct a L{Failure} with an exception type that raises an exception
-        from its C{__str__} method and then call C{getTraceback} with the
-        specified detail and verify that it returns a string.
-        """
-        f = failure.Failure(BrokenExceptionType())
-        traceback = f.getTraceback(detail=detail)
-        self.assertIsInstance(traceback, str)
-
-    def test_brokenTypeBriefDetail(self) -> None:
-        """
-                A L{Failure} might wrap an
-                newPublisher(evt)
-        xception the type object of which has a
-                C{__str__} method which raises an exception.  In this case, calling
-                C{getTraceback} on the failure with the C{"brief"} detail does not raise
-                an exception.
-        """
-        self._brokenTypeTest("brief")
-
-    def test_brokenTypeDefaultDetail(self) -> None:
-        """
-        Like test_brokenTypeBriefDetail, but for the C{"default"} detail case.
-        """
-        self._brokenTypeTest("default")
-
-    def test_brokenTypeVerboseDetail(self) -> None:
-        """
-        Like test_brokenTypeBriefDetail, but for the C{"verbose"} detail case.
-        """
-        self._brokenTypeTest("verbose")
-
-
-class FindFailureTests(SynchronousTestCase):
-    """
-    Tests for functionality related to identifying the C{Failure}.
-    """
-
-    @skipIf(raiser is None, "raiser extension not available")
-    def test_failureConstructionWithMungedStackSucceeds(self) -> None:
-        """
-        Pyrex and Cython are known to insert fake stack frames so as to give
-        more Python-like tracebacks. These stack frames with empty code objects
-        should not break extraction of the exception.
-        """
-        try:
-            raiser.raiseException()
-        except raiser.RaiserException:
-            f = failure.Failure()
-            self.assertTrue(f.check(raiser.RaiserException))
-        else:
-            self.fail("No exception raised from extension?!")
-
-
-# On Python 3.5, extract_tb returns "FrameSummary" objects, which are almost
-# like the old tuples. This being different does not affect the actual tests
-# as we are testing that the input works, and that extract_tb returns something
-# reasonable.
-def _tb(fn: str, lineno: int, name: str, text: None) -> FrameSummary:
-    return FrameSummary(fn, lineno, name)
-
-
-class FormattableTracebackTests(SynchronousTestCase):
-    """
-    Whitebox tests that show that L{failure._Traceback} constructs objects that
-    can be used by L{traceback.extract_tb}.
-
-    If the objects can be used by L{traceback.extract_tb}, then they can be
-    formatted using L{traceback.format_tb} and friends.
-    """
-
-    def test_singleFrame(self) -> None:
-        """
-        A C{_Traceback} object constructed with a single frame should be able
-        to be passed to L{traceback.extract_tb}, and we should get a singleton
-        list containing a (filename, lineno, methodname, line) tuple.
-        """
-        tb = failure._Traceback([["method", "filename.py", 123, {}, {}]])
-        # Note that we don't need to test that extract_tb correctly extracts
-        # the line's contents. In this case, since filename.py doesn't exist,
-        # it will just use None.
-        self.assertEqual(
-            traceback.extract_tb(tb), [_tb("filename.py", 123, "method", None)]
-        )
-
-    def test_manyFrames(self) -> None:
-        """
-        A C{_Traceback} object constructed with multiple frames should be able
-        to be passed to L{traceback.extract_tb}, and we should get a list
-        containing a tuple for each frame.
-        """
-        tb = failure._Traceback(
-            [
-                ["method1", "filename.py", 123, {}, {}],
-                ["method2", "filename.py", 235, {}, {}],
-            ],
-        )
-        self.assertEqual(
-            traceback.extract_tb(tb),
-            [
-                _tb("filename.py", 123, "method1", None),
-                _tb("filename.py", 235, "method2", None),
-            ],
-        )
-
-        # We should also be able to extract_stack on it
-        self.assertEqual(
-            traceback.extract_stack(tb.tb_frame),
-            [
-                _tb("filename.py", 123, "method1", None),
-            ],
-        )
-
-
-class FakeAttributesTests(SynchronousTestCase):
-    """
-    _Frame, _Code and _TracebackFrame objects should possess some basic
-    attributes that qualify them as fake python objects, allowing the return of
-    _Traceback to be used as a fake traceback. The attributes that have zero or
-    empty values are there so that things expecting them find them (e.g. post
-    mortem debuggers).
-    """
-
-    def test_fakeFrameAttributes(self) -> None:
-        """
-        L{_Frame} instances have the C{f_globals} and C{f_locals} attributes
-        bound to C{dict} instance.  They also have the C{f_code} attribute
-        bound to something like a code object.
-        """
-        back_frame = failure._Frame(
-            (
-                "dummyparent",
-                "dummyparentfile",
-                111,
-                None,
-                None,
-            ),
-            None,
-        )
-        fake_locals = {"local_var": 42}
-        fake_globals = {"global_var": 100}
-        frame = failure._Frame(
-            (
-                "dummyname",
-                "dummyfilename",
-                42,
-                fake_locals,
-                fake_globals,
-            ),
-            back_frame,
-        )
-        self.assertEqual(frame.f_globals, fake_globals)
-        self.assertEqual(frame.f_locals, fake_locals)
-        self.assertIsInstance(frame.f_code, failure._Code)
-        self.assertEqual(frame.f_back, back_frame)
-        self.assertIsInstance(frame.f_builtins, dict)
-        self.assertIsInstance(frame.f_lasti, int)
-        self.assertEqual(frame.f_lineno, 42)
-        self.assertIsInstance(frame.f_trace, type(None))
-
-    def test_fakeCodeAttributes(self) -> None:
-        """
-        See L{FakeAttributesTests} for more details about this test.
-        """
-        code = failure._Code("dummyname", "dummyfilename")
-        self.assertEqual(code.co_name, "dummyname")
-        self.assertEqual(code.co_filename, "dummyfilename")
-        self.assertIsInstance(code.co_argcount, int)
-        self.assertIsInstance(code.co_code, bytes)
-        self.assertIsInstance(code.co_cellvars, tuple)
-        self.assertIsInstance(code.co_consts, tuple)
-        self.assertIsInstance(code.co_firstlineno, int)
-        self.assertIsInstance(code.co_flags, int)
-        self.assertIsInstance(code.co_lnotab, bytes)
-        self.assertIsInstance(code.co_freevars, tuple)
-        self.assertIsInstance(code.co_posonlyargcount, int)
-        self.assertIsInstance(code.co_kwonlyargcount, int)
-        self.assertIsInstance(code.co_names, tuple)
-        self.assertIsInstance(code.co_nlocals, int)
-        self.assertIsInstance(code.co_stacksize, int)
-        self.assertIsInstance(code.co_varnames, list)
-        self.assertIsInstance(code.co_positions(), tuple)
-
-    def test_fakeTracebackFrame(self) -> None:
-        """
-        See L{FakeAttributesTests} for more details about this test.
-        """
-        frame = failure._Frame(
-            ("dummyname", "dummyfilename", 42, {}, {}),
-            None,
-        )
-        traceback_frame = failure._TracebackFrame(frame)
-        self.assertEqual(traceback_frame.tb_frame, frame)
-        self.assertEqual(traceback_frame.tb_lineno, 42)
-        self.assertIsInstance(traceback_frame.tb_lasti, int)
-        self.assertTrue(hasattr(traceback_frame, "tb_next"))
-
-
-class DebugModeTests(SynchronousTestCase):
-    """
-    Failure's debug mode should allow jumping into the debugger.
-    """
-
-    def setUp(self) -> None:
-        """
-        Override pdb.post_mortem so we can make sure it's called.
-        """
-        # Make sure any changes we make are reversed:
-        post_mortem = pdb.post_mortem
-        origInit = failure.Failure.__init__
-
-        def restore() -> None:
-            pdb.post_mortem = post_mortem
-            failure.Failure.__init__ = origInit  # type: ignore[method-assign]
-
-        self.addCleanup(restore)
-
-        self.result: list[TracebackType | None] = []
-
-        def logging_post_mortem(t: TracebackType | None = None) -> None:
-            self.result.append(t)
-
-        pdb.post_mortem = logging_post_mortem
-        failure.startDebugMode()
-
-    def test_regularFailure(self) -> None:
-        """
-        If startDebugMode() is called, calling Failure() will first call
-        pdb.post_mortem with the traceback.
-        """
-        try:
-            1 / 0
-        except BaseException:
-            typ, exc, tb = sys.exc_info()
-            f = failure.Failure()
-        self.assertEqual(self.result, [tb])
-        self.assertFalse(f.captureVars)
-
-    def test_captureVars(self) -> None:
-        """
-        If startDebugMode() is called, passing captureVars to Failure() will
-        not blow up.
-        """
-        try:
-            1 / 0
-        except BaseException:
-            typ, exc, tb = sys.exc_info()
-            f = failure.Failure(captureVars=True)
-        self.assertEqual(self.result, [tb])
-        self.assertTrue(f.captureVars)
-
-
-class ExtendedGeneratorTests(SynchronousTestCase):
-    """
-    Tests C{failure.Failure} support for generator features added in Python 2.5
-    """
-
-    def _throwIntoGenerator(
-        self, f: failure.Failure, g: Generator[Any, Any, Any]
-    ) -> None:
-        try:
-            f.throwExceptionIntoGenerator(g)
-        except StopIteration:
-            pass
-        else:
-            self.fail("throwExceptionIntoGenerator should have raised " "StopIteration")
-
-    def test_throwExceptionIntoGenerator(self) -> None:
-        """
-        It should be possible to throw the exception that a Failure
-        represents into a generator.
-        """
-        stuff = []
-
-        def generator() -> Generator[None, None, None]:
-            try:
-                yield
-            except BaseException:
-                stuff.append(sys.exc_info())
-            else:
-                self.fail("Yield should have yielded exception.")
-
-        g = generator()
-        f = getDivisionFailure()
-        next(g)
-        self._throwIntoGenerator(f, g)
-
-        self.assertEqual(stuff[0][0], ZeroDivisionError)
-        self.assertIsInstance(stuff[0][1], ZeroDivisionError)
-
-        self.assertEqual(traceback.extract_tb(stuff[0][2])[-1][-1], "1 / 0")
-
-    def test_failureConstructionFindsOriginalFailure(self) -> None:
-        """
-        When a Failure is constructed in the context of an exception
-        handler that is handling an exception raised by
-        throwExceptionIntoGenerator, the new Failure should be chained to that
-        original Failure.
-        """
-        f = getDivisionFailure()
-        f.cleanFailure()
-        original_failure_str = f.getTraceback()
-
-        newFailures = []
-
-        def generator() -> Generator[None, None, None]:
-            try:
-                yield
-            except BaseException:
-                newFailures.append(failure.Failure())
-            else:
-                self.fail("No exception sent to generator")
-
-        g = generator()
-        next(g)
-        self._throwIntoGenerator(f, g)
-
-        self.assertEqual(len(newFailures), 1)
-
-        # The original failure should not be changed.
-        self.assertEqual(original_failure_str, f.getTraceback())
-
-        # The new failure should be different and contain stack info for
-        # our generator.
-        self.assertNotEqual(newFailures[0].getTraceback(), f.getTraceback())
-        self.assertIn("generator", newFailures[0].getTraceback())
-        self.assertNotIn("generator", f.getTraceback())
-
-    def test_ambiguousFailureInGenerator(self) -> None:
-        """
-        When a generator reraises a different exception, creating a L{Failure}
-        inside the generator should find the reraised exception rather than
-        original one.
-        """
-
-        def generator() -> Generator[None, None, None]:
-            try:
-                try:
-                    yield
-                except BaseException:
-                    [][1]
-            except BaseException:
-                self.assertIsInstance(failure.Failure().value, IndexError)
-
-        g = generator()
-        next(g)
-        f = getDivisionFailure()
-        self._throwIntoGenerator(f, g)
-
-    def test_ambiguousFailureFromGenerator(self) -> None:
-        """
-        When a generator reraises a different exception, creating a L{Failure}
-        above the generator should find the reraised exception rather than
-        original one.
-        """
-
-        def generator() -> Generator[None, None, None]:
-            try:
-                yield
-            except BaseException:
-                [][1]
-
-        g = generator()
-        next(g)
-        f = getDivisionFailure()
-        try:
-            self._throwIntoGenerator(f, g)
-        except BaseException:
-            self.assertIsInstance(failure.Failure().value, IndexError)
