| 714 | return self |
| 715 | |
| 716 | async def __aexit__(self, *exc_details): |
| 717 | exc = exc_details[1] |
| 718 | received_exc = exc is not None |
| 719 | |
| 720 | # We manipulate the exception state so it behaves as though |
| 721 | # we were actually nesting multiple with statements |
| 722 | frame_exc = sys.exception() |
| 723 | def _fix_exception_context(new_exc, old_exc): |
| 724 | # Context may not be correct, so find the end of the chain |
| 725 | while 1: |
| 726 | exc_context = new_exc.__context__ |
| 727 | if exc_context is None or exc_context is old_exc: |
| 728 | # Context is already set correctly (see issue 20317) |
| 729 | return |
| 730 | if exc_context is frame_exc: |
| 731 | break |
| 732 | new_exc = exc_context |
| 733 | # Change the end of the chain to point to the exception |
| 734 | # we expect it to reference |
| 735 | new_exc.__context__ = old_exc |
| 736 | |
| 737 | # Callbacks are invoked in LIFO order to match the behaviour of |
| 738 | # nested context managers |
| 739 | suppressed_exc = False |
| 740 | pending_raise = False |
| 741 | while self._exit_callbacks: |
| 742 | is_sync, cb = self._exit_callbacks.pop() |
| 743 | try: |
| 744 | if exc is None: |
| 745 | exc_details = None, None, None |
| 746 | else: |
| 747 | exc_details = type(exc), exc, exc.__traceback__ |
| 748 | if is_sync: |
| 749 | cb_suppress = cb(*exc_details) |
| 750 | else: |
| 751 | cb_suppress = await cb(*exc_details) |
| 752 | |
| 753 | if cb_suppress: |
| 754 | suppressed_exc = True |
| 755 | pending_raise = False |
| 756 | exc = None |
| 757 | except BaseException as new_exc: |
| 758 | # simulate the stack of exceptions by setting the context |
| 759 | _fix_exception_context(new_exc, exc) |
| 760 | pending_raise = True |
| 761 | exc = new_exc |
| 762 | |
| 763 | if pending_raise: |
| 764 | try: |
| 765 | # bare "raise exc" replaces our carefully |
| 766 | # set-up context |
| 767 | fixed_ctx = exc.__context__ |
| 768 | raise exc |
| 769 | except BaseException: |
| 770 | exc.__context__ = fixed_ctx |
| 771 | raise |
| 772 | return received_exc and suppressed_exc |
| 773 | |