Twisted passes a custom Failure instance to `addError()` instead of using `sys.exc_info()`. Therefore, if `rawexcinfo` is a `Failure` instance, convert it into the equivalent `sys.exc_info()` tuple as expected by pytest.
(
rawexcinfo: _SysExcInfoType | BaseException,
)
| 613 | |
| 614 | |
| 615 | def _handle_twisted_exc_info( |
| 616 | rawexcinfo: _SysExcInfoType | BaseException, |
| 617 | ) -> _SysExcInfoType: |
| 618 | """ |
| 619 | Twisted passes a custom Failure instance to `addError()` instead of using `sys.exc_info()`. |
| 620 | Therefore, if `rawexcinfo` is a `Failure` instance, convert it into the equivalent `sys.exc_info()` tuple |
| 621 | as expected by pytest. |
| 622 | """ |
| 623 | twisted_version = _get_twisted_version() |
| 624 | if twisted_version is TwistedVersion.NotInstalled: |
| 625 | # Unfortunately, because we cannot import `twisted.python.failure` at the top of the file |
| 626 | # and use it in the signature, we need to use `type:ignore` here because we cannot narrow |
| 627 | # the type properly in the `if` statement above. |
| 628 | return rawexcinfo # type:ignore[return-value] |
| 629 | elif twisted_version is TwistedVersion.Version24: |
| 630 | # Twisted calls addError() passing its own classes (like `twisted.python.Failure`), which violates |
| 631 | # the `addError()` signature, so we extract the original `sys.exc_info()` tuple which is stored |
| 632 | # in the object. |
| 633 | if hasattr(rawexcinfo, TWISTED_RAW_EXCINFO_ATTR): |
| 634 | saved_exc_info = getattr(rawexcinfo, TWISTED_RAW_EXCINFO_ATTR) |
| 635 | # Delete the attribute from the original object to avoid leaks. |
| 636 | delattr(rawexcinfo, TWISTED_RAW_EXCINFO_ATTR) |
| 637 | return saved_exc_info # type:ignore[no-any-return] |
| 638 | return rawexcinfo # type:ignore[return-value] |
| 639 | elif twisted_version is TwistedVersion.Version25: |
| 640 | if isinstance(rawexcinfo, BaseException): |
| 641 | import twisted.python.failure |
| 642 | |
| 643 | if isinstance(rawexcinfo, twisted.python.failure.Failure): |
| 644 | tb = rawexcinfo.__traceback__ |
| 645 | if tb is None: |
| 646 | tb = sys.exc_info()[2] |
| 647 | return type(rawexcinfo.value), rawexcinfo.value, tb |
| 648 | |
| 649 | return rawexcinfo # type:ignore[return-value] |
| 650 | else: |
| 651 | # Ideally we would use assert_never() here, but it is not available in all Python versions |
| 652 | # we support, plus we do not require `type_extensions` currently. |
| 653 | assert False, f"Unexpected Twisted version: {twisted_version}" |
no test coverage detected