Skip to content

Instantly share code, notes, and snippets.

@ktbarrett
Created January 20, 2026 19:03
Show Gist options
  • Select an option

  • Save ktbarrett/5cf2553d90e470c370a078c56d52cd96 to your computer and use it in GitHub Desktop.

Select an option

Save ktbarrett/5cf2553d90e470c370a078c56d52cd96 to your computer and use it in GitHub Desktop.
Create dynamic stack of context managers
from contextlib import AbstractContextManager
import sys
from types import TracebackType
class ContextManagerStack(AbstractContextManager):
def __init__(self, *contextManagers: AbstractContextManager) -> None:
self._contextManagers = contextManagers
self._enteredContexts: list[AbstractContextManager] = []
def __enter__(self) -> tuple[object, ...]:
res: list[object] = []
for cm in self._contextManagers:
try:
r = cm.__enter__()
except Exception:
self.__exit__(*sys.exc_info())
else:
res.append(r)
self._enteredContexts.append(cm)
return tuple(res)
def __exit__(self, excType: type[BaseException] | None, excValue: BaseException | None, traceback: TracebackType | None) -> None:
excs: list[Exception] = []
if excValue is not None:
excs.append(excValue)
while self._enteredContexts:
cm = self._enteredContexts.pop()
try:
cm.__exit__(excType, excValue, traceback)
except Exception as e:
excs.append(e)
if excs:
raise ExceptionGroup("Multiple exceptions in ContextManagerStack", excs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment