jpayne@68: Metadata-Version: 2.1 jpayne@68: Name: exceptiongroup jpayne@68: Version: 1.2.2 jpayne@68: Summary: Backport of PEP 654 (exception groups) jpayne@68: Author-email: Alex Grönholm jpayne@68: Requires-Python: >=3.7 jpayne@68: Description-Content-Type: text/x-rst jpayne@68: Classifier: Development Status :: 5 - Production/Stable jpayne@68: Classifier: Intended Audience :: Developers jpayne@68: Classifier: License :: OSI Approved :: MIT License jpayne@68: Classifier: Programming Language :: Python jpayne@68: Classifier: Programming Language :: Python :: 3 :: Only jpayne@68: Classifier: Typing :: Typed jpayne@68: Requires-Dist: pytest >= 6 ; extra == "test" jpayne@68: Project-URL: Changelog, https://github.com/agronholm/exceptiongroup/blob/main/CHANGES.rst jpayne@68: Project-URL: Issue Tracker, https://github.com/agronholm/exceptiongroup/issues jpayne@68: Project-URL: Source code, https://github.com/agronholm/exceptiongroup jpayne@68: Provides-Extra: test jpayne@68: jpayne@68: .. image:: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml/badge.svg jpayne@68: :target: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml jpayne@68: :alt: Build Status jpayne@68: .. image:: https://coveralls.io/repos/github/agronholm/exceptiongroup/badge.svg?branch=main jpayne@68: :target: https://coveralls.io/github/agronholm/exceptiongroup?branch=main jpayne@68: :alt: Code Coverage jpayne@68: jpayne@68: This is a backport of the ``BaseExceptionGroup`` and ``ExceptionGroup`` classes from jpayne@68: Python 3.11. jpayne@68: jpayne@68: It contains the following: jpayne@68: jpayne@68: * The ``exceptiongroup.BaseExceptionGroup`` and ``exceptiongroup.ExceptionGroup`` jpayne@68: classes jpayne@68: * A utility function (``exceptiongroup.catch()``) for catching exceptions possibly jpayne@68: nested in an exception group jpayne@68: * Patches to the ``TracebackException`` class that properly formats exception groups jpayne@68: (installed on import) jpayne@68: * An exception hook that handles formatting of exception groups through jpayne@68: ``TracebackException`` (installed on import) jpayne@68: * Special versions of some of the functions from the ``traceback`` module, modified to jpayne@68: correctly handle exception groups even when monkey patching is disabled, or blocked by jpayne@68: another custom exception hook: jpayne@68: jpayne@68: * ``traceback.format_exception()`` jpayne@68: * ``traceback.format_exception_only()`` jpayne@68: * ``traceback.print_exception()`` jpayne@68: * ``traceback.print_exc()`` jpayne@68: * A backported version of ``contextlib.suppress()`` from Python 3.12.1 which also jpayne@68: handles suppressing exceptions inside exception groups jpayne@68: jpayne@68: If this package is imported on Python 3.11 or later, the built-in implementations of the jpayne@68: exception group classes are used instead, ``TracebackException`` is not monkey patched jpayne@68: and the exception hook won't be installed. jpayne@68: jpayne@68: See the `standard library documentation`_ for more information on exception groups. jpayne@68: jpayne@68: .. _standard library documentation: https://docs.python.org/3/library/exceptions.html jpayne@68: jpayne@68: Catching exceptions jpayne@68: =================== jpayne@68: jpayne@68: Due to the lack of the ``except*`` syntax introduced by `PEP 654`_ in earlier Python jpayne@68: versions, you need to use ``exceptiongroup.catch()`` to catch exceptions that are jpayne@68: potentially nested inside an exception group. This function returns a context manager jpayne@68: that calls the given handler for any exceptions matching the sole argument. jpayne@68: jpayne@68: The argument to ``catch()`` must be a dict (or any ``Mapping``) where each key is either jpayne@68: an exception class or an iterable of exception classes. Each value must be a callable jpayne@68: that takes a single positional argument. The handler will be called at most once, with jpayne@68: an exception group as an argument which will contain all the exceptions that are any jpayne@68: of the given types, or their subclasses. The exception group may contain nested groups jpayne@68: containing more matching exceptions. jpayne@68: jpayne@68: Thus, the following Python 3.11+ code: jpayne@68: jpayne@68: .. code-block:: python jpayne@68: jpayne@68: try: jpayne@68: ... jpayne@68: except* (ValueError, KeyError) as excgroup: jpayne@68: for exc in excgroup.exceptions: jpayne@68: print('Caught exception:', type(exc)) jpayne@68: except* RuntimeError: jpayne@68: print('Caught runtime error') jpayne@68: jpayne@68: would be written with this backport like this: jpayne@68: jpayne@68: .. code-block:: python jpayne@68: jpayne@68: from exceptiongroup import BaseExceptionGroup, catch jpayne@68: jpayne@68: def value_key_err_handler(excgroup: BaseExceptionGroup) -> None: jpayne@68: for exc in excgroup.exceptions: jpayne@68: print('Caught exception:', type(exc)) jpayne@68: jpayne@68: def runtime_err_handler(exc: BaseExceptionGroup) -> None: jpayne@68: print('Caught runtime error') jpayne@68: jpayne@68: with catch({ jpayne@68: (ValueError, KeyError): value_key_err_handler, jpayne@68: RuntimeError: runtime_err_handler jpayne@68: }): jpayne@68: ... jpayne@68: jpayne@68: **NOTE**: Just like with ``except*``, you cannot handle ``BaseExceptionGroup`` or jpayne@68: ``ExceptionGroup`` with ``catch()``. jpayne@68: jpayne@68: Suppressing exceptions jpayne@68: ====================== jpayne@68: jpayne@68: This library contains a backport of the ``contextlib.suppress()`` context manager from jpayne@68: Python 3.12.1. It allows you to selectively ignore certain exceptions, even when they're jpayne@68: inside exception groups: jpayne@68: jpayne@68: .. code-block:: python jpayne@68: jpayne@68: from exceptiongroup import suppress jpayne@68: jpayne@68: with suppress(RuntimeError): jpayne@68: raise ExceptionGroup("", [RuntimeError("boo")]) jpayne@68: jpayne@68: Notes on monkey patching jpayne@68: ======================== jpayne@68: jpayne@68: To make exception groups render properly when an unhandled exception group is being jpayne@68: printed out, this package does two things when it is imported on any Python version jpayne@68: earlier than 3.11: jpayne@68: jpayne@68: #. The ``traceback.TracebackException`` class is monkey patched to store extra jpayne@68: information about exception groups (in ``__init__()``) and properly format them (in jpayne@68: ``format()``) jpayne@68: #. An exception hook is installed at ``sys.excepthook``, provided that no other hook is jpayne@68: already present. This hook causes the exception to be formatted using jpayne@68: ``traceback.TracebackException`` rather than the built-in rendered. jpayne@68: jpayne@68: If ``sys.exceptionhook`` is found to be set to something else than the default when jpayne@68: ``exceptiongroup`` is imported, no monkeypatching is done at all. jpayne@68: jpayne@68: To prevent the exception hook and patches from being installed, set the environment jpayne@68: variable ``EXCEPTIONGROUP_NO_PATCH`` to ``1``. jpayne@68: jpayne@68: Formatting exception groups jpayne@68: --------------------------- jpayne@68: jpayne@68: Normally, the monkey patching applied by this library on import will cause exception jpayne@68: groups to be printed properly in tracebacks. But in cases when the monkey patching is jpayne@68: blocked by a third party exception hook, or monkey patching is explicitly disabled, jpayne@68: you can still manually format exceptions using the special versions of the ``traceback`` jpayne@68: functions, like ``format_exception()``, listed at the top of this page. They work just jpayne@68: like their counterparts in the ``traceback`` module, except that they use a separately jpayne@68: patched subclass of ``TracebackException`` to perform the rendering. jpayne@68: jpayne@68: Particularly in cases where a library installs its own exception hook, it is recommended jpayne@68: to use these special versions to do the actual formatting of exceptions/tracebacks. jpayne@68: jpayne@68: .. _PEP 654: https://www.python.org/dev/peps/pep-0654/ jpayne@68: