MCPcopy Index your code
hub / github.com/python/cpython / ExitStack

Class ExitStack

Lib/contextlib.py:554–624  ·  view source on GitHub ↗

Context manager for dynamic management of a stack of exit callbacks. For example: with ExitStack() as stack: files = [stack.enter_context(open(fname)) for fname in filenames] # All opened files will automatically be closed at the end of # the with sta

Source from the content-addressed store, hash-verified

552
553# Inspired by discussions on http://bugs.python.org/issue13585
554class ExitStack(_BaseExitStack, AbstractContextManager):
555 """Context manager for dynamic management of a stack of exit callbacks.
556
557 For example:
558 with ExitStack() as stack:
559 files = [stack.enter_context(open(fname)) for fname in filenames]
560 # All opened files will automatically be closed at the end of
561 # the with statement, even if attempts to open files later
562 # in the list raise an exception.
563 """
564
565 def __enter__(self):
566 return self
567
568 def __exit__(self, *exc_details):
569 exc = exc_details[1]
570 received_exc = exc is not None
571
572 # We manipulate the exception state so it behaves as though
573 # we were actually nesting multiple with statements
574 frame_exc = sys.exception()
575 def _fix_exception_context(new_exc, old_exc):
576 # Context may not be correct, so find the end of the chain
577 while 1:
578 exc_context = new_exc.__context__
579 if exc_context is None or exc_context is old_exc:
580 # Context is already set correctly (see issue 20317)
581 return
582 if exc_context is frame_exc:
583 break
584 new_exc = exc_context
585 # Change the end of the chain to point to the exception
586 # we expect it to reference
587 new_exc.__context__ = old_exc
588
589 # Callbacks are invoked in LIFO order to match the behaviour of
590 # nested context managers
591 suppressed_exc = False
592 pending_raise = False
593 while self._exit_callbacks:
594 is_sync, cb = self._exit_callbacks.pop()
595 assert is_sync
596 try:
597 if exc is None:
598 exc_details = None, None, None
599 else:
600 exc_details = type(exc), exc, exc.__traceback__
601 if cb(*exc_details):
602 suppressed_exc = True
603 pending_raise = False
604 exc = None
605 except BaseException as new_exc:
606 # simulate the stack of exceptions by setting the context
607 _fix_exception_context(new_exc, exc)
608 pending_raise = True
609 exc = new_exc
610
611 if pending_raise:

Callers 10

attachFunction · 0.90
stream_contextMethod · 0.90
do_testMethod · 0.90
setUpMethod · 0.90
test_headerMethod · 0.90
mock_sysMethod · 0.90
setUpClassMethod · 0.90
test_all_watchersMethod · 0.90
run_ptyFunction · 0.90

Calls

no outgoing calls

Tested by 8

stream_contextMethod · 0.72
do_testMethod · 0.72
setUpMethod · 0.72
test_headerMethod · 0.72
mock_sysMethod · 0.72
setUpClassMethod · 0.72
test_all_watchersMethod · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…