Skip to content
This repository was archived by the owner on Nov 2, 2022. It is now read-only.

add API to generate leaf exception from exceptongroup #13

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions exceptiongroup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from ._version import __version__

__all__ = ["ExceptionGroup", "split", "catch"]
__all__ = ["ExceptionGroup", "split", "catch", "leaf_exceptions"]


class ExceptionGroup(BaseException):
Expand Down Expand Up @@ -54,4 +54,4 @@ def __copy__(self):


from . import _monkeypatch
from ._tools import split, catch
from ._tools import split, catch, leaf_exceptions
40 changes: 39 additions & 1 deletion exceptiongroup/_tests/test_tools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from collections.abc import Iterable
import pytest
from exceptiongroup import ExceptionGroup, split

from exceptiongroup import ExceptionGroup, split, leaf_exceptions


def raise_error(err):
Expand Down Expand Up @@ -115,3 +117,39 @@ def test_split_and_check_attributes_same():
assert unmatched.__traceback__ is new_group.__traceback__
assert unmatched.__cause__ is new_group.__cause__
assert unmatched.__context__ is new_group.__context__


def test_leaf_exceptions_iterable():
group = ExceptionGroup("error", [RuntimeError("error1")], ["error1"])
result = leaf_exceptions(group)
assert isinstance(result, Iterable)


def test_leaf_exceptions_values():
leaf_error1 = RuntimeError("Error1")
leaf_error2 = RuntimeError("Error2")
group = ExceptionGroup(
"error", [leaf_error1, leaf_error2], ["Error1", "Error2"]
)
result = list(leaf_exceptions(group))
assert result == [leaf_error1, leaf_error2]

# test for exception group which contains nested group
group = ExceptionGroup(
"error",
[leaf_error1, ExceptionGroup("Error2", [leaf_error2], ["Error2"])],
["Error1", "Error2"],
)
result = list(leaf_exceptions(group))
assert result == [leaf_error1, leaf_error2]


def test_leaf_exceptions_with_bare_exception():
error1 = RuntimeError("Error1")
result = list(leaf_exceptions(error1))
assert result == [error1]


def test_leaf_exception_with_non_exception_object():
with pytest.raises(TypeError):
list(leaf_exceptions(None))
19 changes: 19 additions & 0 deletions exceptiongroup/_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@
from . import ExceptionGroup


def leaf_exceptions(exc):
""" Iterate and extract sub exceptions from given exception.

Args:
exc (BaseException): Exception object we want to extract.
Yields:
leaf exception object.
"""
if not isinstance(exc, BaseException):
raise TypeError(
"Argument `exc` should be an instance of BaseException."
)
if isinstance(exc, ExceptionGroup):
for subexc in exc.exceptions:
yield from leaf_exceptions(subexc)
else:
yield exc


def split(exc_type, exc, *, match=None):
""" splits the exception into one half (matched) representing all the parts of
the exception that match the predicate, and another half (not matched)
Expand Down