1 from __future__ import annotations 2 3 import sys 4 from contextlib import AbstractContextManager 5 from types import TracebackType 6 from typing import TYPE_CHECKING, Optional, Type, cast 7 8 if sys.version_info < (3, 11): 9 from ._exceptions import BaseExceptionGroup 10 11 if TYPE_CHECKING: 12 # requires python 3.9 13 BaseClass = AbstractContextManager[None] 14 else: 15 BaseClass = AbstractContextManager 16 17 18 class suppress(BaseClass): 19 """Backport of :class:`contextlib.suppress` from Python 3.12.1.""" 20 21 def __init__(self, *exceptions: type[BaseException]): 22 self._exceptions = exceptions 23 24 def __enter__(self) -> None: 25 pass 26 27 def __exit__( 28 self, 29 exctype: Optional[Type[BaseException]], 30 excinst: Optional[BaseException], 31 exctb: Optional[TracebackType], 32 ) -> bool: 33 # Unlike isinstance and issubclass, CPython exception handling 34 # currently only looks at the concrete type hierarchy (ignoring 35 # the instance and subclass checking hooks). While Guido considers 36 # that a bug rather than a feature, it's a fairly hard one to fix 37 # due to various internal implementation details. suppress provides 38 # the simpler issubclass based semantics, rather than trying to 39 # exactly reproduce the limitations of the CPython interpreter. 40 # 41 # See http://bugs.python.org/issue12029 for more details 42 if exctype is None: 43 return False 44 45 if issubclass(exctype, self._exceptions): 46 return True 47 48 if issubclass(exctype, BaseExceptionGroup): 49 match, rest = cast(BaseExceptionGroup, excinst).split(self._exceptions) 50 if rest is None: 51 return True 52 53 raise rest 54 55 return False 56