jpayne@68
|
1 Metadata-Version: 2.1
|
jpayne@68
|
2 Name: exceptiongroup
|
jpayne@68
|
3 Version: 1.2.2
|
jpayne@68
|
4 Summary: Backport of PEP 654 (exception groups)
|
jpayne@68
|
5 Author-email: Alex Grönholm <alex.gronholm@nextday.fi>
|
jpayne@68
|
6 Requires-Python: >=3.7
|
jpayne@68
|
7 Description-Content-Type: text/x-rst
|
jpayne@68
|
8 Classifier: Development Status :: 5 - Production/Stable
|
jpayne@68
|
9 Classifier: Intended Audience :: Developers
|
jpayne@68
|
10 Classifier: License :: OSI Approved :: MIT License
|
jpayne@68
|
11 Classifier: Programming Language :: Python
|
jpayne@68
|
12 Classifier: Programming Language :: Python :: 3 :: Only
|
jpayne@68
|
13 Classifier: Typing :: Typed
|
jpayne@68
|
14 Requires-Dist: pytest >= 6 ; extra == "test"
|
jpayne@68
|
15 Project-URL: Changelog, https://github.com/agronholm/exceptiongroup/blob/main/CHANGES.rst
|
jpayne@68
|
16 Project-URL: Issue Tracker, https://github.com/agronholm/exceptiongroup/issues
|
jpayne@68
|
17 Project-URL: Source code, https://github.com/agronholm/exceptiongroup
|
jpayne@68
|
18 Provides-Extra: test
|
jpayne@68
|
19
|
jpayne@68
|
20 .. image:: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml/badge.svg
|
jpayne@68
|
21 :target: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml
|
jpayne@68
|
22 :alt: Build Status
|
jpayne@68
|
23 .. image:: https://coveralls.io/repos/github/agronholm/exceptiongroup/badge.svg?branch=main
|
jpayne@68
|
24 :target: https://coveralls.io/github/agronholm/exceptiongroup?branch=main
|
jpayne@68
|
25 :alt: Code Coverage
|
jpayne@68
|
26
|
jpayne@68
|
27 This is a backport of the ``BaseExceptionGroup`` and ``ExceptionGroup`` classes from
|
jpayne@68
|
28 Python 3.11.
|
jpayne@68
|
29
|
jpayne@68
|
30 It contains the following:
|
jpayne@68
|
31
|
jpayne@68
|
32 * The ``exceptiongroup.BaseExceptionGroup`` and ``exceptiongroup.ExceptionGroup``
|
jpayne@68
|
33 classes
|
jpayne@68
|
34 * A utility function (``exceptiongroup.catch()``) for catching exceptions possibly
|
jpayne@68
|
35 nested in an exception group
|
jpayne@68
|
36 * Patches to the ``TracebackException`` class that properly formats exception groups
|
jpayne@68
|
37 (installed on import)
|
jpayne@68
|
38 * An exception hook that handles formatting of exception groups through
|
jpayne@68
|
39 ``TracebackException`` (installed on import)
|
jpayne@68
|
40 * Special versions of some of the functions from the ``traceback`` module, modified to
|
jpayne@68
|
41 correctly handle exception groups even when monkey patching is disabled, or blocked by
|
jpayne@68
|
42 another custom exception hook:
|
jpayne@68
|
43
|
jpayne@68
|
44 * ``traceback.format_exception()``
|
jpayne@68
|
45 * ``traceback.format_exception_only()``
|
jpayne@68
|
46 * ``traceback.print_exception()``
|
jpayne@68
|
47 * ``traceback.print_exc()``
|
jpayne@68
|
48 * A backported version of ``contextlib.suppress()`` from Python 3.12.1 which also
|
jpayne@68
|
49 handles suppressing exceptions inside exception groups
|
jpayne@68
|
50
|
jpayne@68
|
51 If this package is imported on Python 3.11 or later, the built-in implementations of the
|
jpayne@68
|
52 exception group classes are used instead, ``TracebackException`` is not monkey patched
|
jpayne@68
|
53 and the exception hook won't be installed.
|
jpayne@68
|
54
|
jpayne@68
|
55 See the `standard library documentation`_ for more information on exception groups.
|
jpayne@68
|
56
|
jpayne@68
|
57 .. _standard library documentation: https://docs.python.org/3/library/exceptions.html
|
jpayne@68
|
58
|
jpayne@68
|
59 Catching exceptions
|
jpayne@68
|
60 ===================
|
jpayne@68
|
61
|
jpayne@68
|
62 Due to the lack of the ``except*`` syntax introduced by `PEP 654`_ in earlier Python
|
jpayne@68
|
63 versions, you need to use ``exceptiongroup.catch()`` to catch exceptions that are
|
jpayne@68
|
64 potentially nested inside an exception group. This function returns a context manager
|
jpayne@68
|
65 that calls the given handler for any exceptions matching the sole argument.
|
jpayne@68
|
66
|
jpayne@68
|
67 The argument to ``catch()`` must be a dict (or any ``Mapping``) where each key is either
|
jpayne@68
|
68 an exception class or an iterable of exception classes. Each value must be a callable
|
jpayne@68
|
69 that takes a single positional argument. The handler will be called at most once, with
|
jpayne@68
|
70 an exception group as an argument which will contain all the exceptions that are any
|
jpayne@68
|
71 of the given types, or their subclasses. The exception group may contain nested groups
|
jpayne@68
|
72 containing more matching exceptions.
|
jpayne@68
|
73
|
jpayne@68
|
74 Thus, the following Python 3.11+ code:
|
jpayne@68
|
75
|
jpayne@68
|
76 .. code-block:: python
|
jpayne@68
|
77
|
jpayne@68
|
78 try:
|
jpayne@68
|
79 ...
|
jpayne@68
|
80 except* (ValueError, KeyError) as excgroup:
|
jpayne@68
|
81 for exc in excgroup.exceptions:
|
jpayne@68
|
82 print('Caught exception:', type(exc))
|
jpayne@68
|
83 except* RuntimeError:
|
jpayne@68
|
84 print('Caught runtime error')
|
jpayne@68
|
85
|
jpayne@68
|
86 would be written with this backport like this:
|
jpayne@68
|
87
|
jpayne@68
|
88 .. code-block:: python
|
jpayne@68
|
89
|
jpayne@68
|
90 from exceptiongroup import BaseExceptionGroup, catch
|
jpayne@68
|
91
|
jpayne@68
|
92 def value_key_err_handler(excgroup: BaseExceptionGroup) -> None:
|
jpayne@68
|
93 for exc in excgroup.exceptions:
|
jpayne@68
|
94 print('Caught exception:', type(exc))
|
jpayne@68
|
95
|
jpayne@68
|
96 def runtime_err_handler(exc: BaseExceptionGroup) -> None:
|
jpayne@68
|
97 print('Caught runtime error')
|
jpayne@68
|
98
|
jpayne@68
|
99 with catch({
|
jpayne@68
|
100 (ValueError, KeyError): value_key_err_handler,
|
jpayne@68
|
101 RuntimeError: runtime_err_handler
|
jpayne@68
|
102 }):
|
jpayne@68
|
103 ...
|
jpayne@68
|
104
|
jpayne@68
|
105 **NOTE**: Just like with ``except*``, you cannot handle ``BaseExceptionGroup`` or
|
jpayne@68
|
106 ``ExceptionGroup`` with ``catch()``.
|
jpayne@68
|
107
|
jpayne@68
|
108 Suppressing exceptions
|
jpayne@68
|
109 ======================
|
jpayne@68
|
110
|
jpayne@68
|
111 This library contains a backport of the ``contextlib.suppress()`` context manager from
|
jpayne@68
|
112 Python 3.12.1. It allows you to selectively ignore certain exceptions, even when they're
|
jpayne@68
|
113 inside exception groups:
|
jpayne@68
|
114
|
jpayne@68
|
115 .. code-block:: python
|
jpayne@68
|
116
|
jpayne@68
|
117 from exceptiongroup import suppress
|
jpayne@68
|
118
|
jpayne@68
|
119 with suppress(RuntimeError):
|
jpayne@68
|
120 raise ExceptionGroup("", [RuntimeError("boo")])
|
jpayne@68
|
121
|
jpayne@68
|
122 Notes on monkey patching
|
jpayne@68
|
123 ========================
|
jpayne@68
|
124
|
jpayne@68
|
125 To make exception groups render properly when an unhandled exception group is being
|
jpayne@68
|
126 printed out, this package does two things when it is imported on any Python version
|
jpayne@68
|
127 earlier than 3.11:
|
jpayne@68
|
128
|
jpayne@68
|
129 #. The ``traceback.TracebackException`` class is monkey patched to store extra
|
jpayne@68
|
130 information about exception groups (in ``__init__()``) and properly format them (in
|
jpayne@68
|
131 ``format()``)
|
jpayne@68
|
132 #. An exception hook is installed at ``sys.excepthook``, provided that no other hook is
|
jpayne@68
|
133 already present. This hook causes the exception to be formatted using
|
jpayne@68
|
134 ``traceback.TracebackException`` rather than the built-in rendered.
|
jpayne@68
|
135
|
jpayne@68
|
136 If ``sys.exceptionhook`` is found to be set to something else than the default when
|
jpayne@68
|
137 ``exceptiongroup`` is imported, no monkeypatching is done at all.
|
jpayne@68
|
138
|
jpayne@68
|
139 To prevent the exception hook and patches from being installed, set the environment
|
jpayne@68
|
140 variable ``EXCEPTIONGROUP_NO_PATCH`` to ``1``.
|
jpayne@68
|
141
|
jpayne@68
|
142 Formatting exception groups
|
jpayne@68
|
143 ---------------------------
|
jpayne@68
|
144
|
jpayne@68
|
145 Normally, the monkey patching applied by this library on import will cause exception
|
jpayne@68
|
146 groups to be printed properly in tracebacks. But in cases when the monkey patching is
|
jpayne@68
|
147 blocked by a third party exception hook, or monkey patching is explicitly disabled,
|
jpayne@68
|
148 you can still manually format exceptions using the special versions of the ``traceback``
|
jpayne@68
|
149 functions, like ``format_exception()``, listed at the top of this page. They work just
|
jpayne@68
|
150 like their counterparts in the ``traceback`` module, except that they use a separately
|
jpayne@68
|
151 patched subclass of ``TracebackException`` to perform the rendering.
|
jpayne@68
|
152
|
jpayne@68
|
153 Particularly in cases where a library installs its own exception hook, it is recommended
|
jpayne@68
|
154 to use these special versions to do the actual formatting of exceptions/tracebacks.
|
jpayne@68
|
155
|
jpayne@68
|
156 .. _PEP 654: https://www.python.org/dev/peps/pep-0654/
|
jpayne@68
|
157
|