Skip to content

Commit

Permalink
errors: switch to ExceptionGroup
Browse files Browse the repository at this point in the history
python-3.11 brings ExceptionGroup feature which is very useful for
our use case where we need to teardown multiple objects eventhough
some of them failed.

With ExceptionGroup, no exception and its traceback is lost.

See:
https://peps.python.org/pep-0654/
  • Loading branch information
pbrezina committed Jul 3, 2024
1 parent a6b1c48 commit 51cc9d9
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 9 deletions.
3 changes: 2 additions & 1 deletion pytest_mh/_private/artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import TYPE_CHECKING, Literal, Protocol, TypeAlias, get_args

from ..ssh import SSHLog
from .errors import ArtifactsExceptionGroup
from .misc import sanitize_path, should_collect_artifacts
from .types import MultihostOSFamily, MultihostOutcome

Expand Down Expand Up @@ -249,7 +250,7 @@ def collect(
errors.append(e)

if errors:
raise Exception(errors)
raise ArtifactsExceptionGroup("Unable to collect artifacts from all hosts", errors)

# Sort artifacts by name
artifacts = sorted(artifacts_set)
Expand Down
17 changes: 17 additions & 0 deletions pytest_mh/_private/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from __future__ import annotations


class ArtifactsExceptionGroup(ExceptionGroup):
"""
One or more exception occurred during artifacts collection.
"""

...


class TeardownExceptionGroup(ExceptionGroup):
"""
One or more exception occurred during teardown phase.
"""

...
9 changes: 5 additions & 4 deletions pytest_mh/_private/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from .artifacts import MultihostArtifactsCollectable
from .data import MultihostItemData
from .errors import TeardownExceptionGroup
from .logging import MultihostLogger
from .marks import TopologyMark
from .misc import invoke_callback
Expand Down Expand Up @@ -284,7 +285,7 @@ def _teardown_roles(self) -> None:
errors.append(e)

if errors:
raise Exception(errors)
raise TeardownExceptionGroup("Unable to teardown some roles (role.teardown)", errors)

def _teardown_utils(self) -> None:
"""
Expand Down Expand Up @@ -313,7 +314,7 @@ def _teardown_hosts(self) -> None:
errors.append(e)

if errors:
raise Exception(errors)
raise TeardownExceptionGroup("Unable to teardown some hosts (host.teardown)", errors)

def _teardown_hosts_utils(self) -> None:
"""
Expand All @@ -327,7 +328,7 @@ def _teardown_hosts_utils(self) -> None:
errors.append(e)

if errors:
raise Exception(errors)
raise TeardownExceptionGroup("Unable to exit some utilities (util.__exit__)", errors)

def _pytest_report_teststatus(
self, report: pytest.CollectReport | pytest.TestReport, config: pytest.Config
Expand Down Expand Up @@ -438,7 +439,7 @@ def _exit(self) -> None:

errors = [x for x in errors if x is not None]
if errors:
raise Exception(errors)
raise TeardownExceptionGroup("One or more error occurred during test teardown", errors)


@pytest.fixture(scope="function")
Expand Down
5 changes: 3 additions & 2 deletions pytest_mh/_private/multihost.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
MultihostArtifactsType,
MultihostHostArtifacts,
)
from .errors import TeardownExceptionGroup
from .logging import MultihostHostLogger, MultihostLogger
from .misc import OperationStatus
from .topology import Topology
Expand Down Expand Up @@ -1195,7 +1196,7 @@ def mh_utility_teardown_dependencies(
errors.append(e)

if errors:
raise Exception(errors)
raise TeardownExceptionGroup("Unable to teardown some utilities (util.teardown)", errors)


def mh_utility_enter_dependencies(obj: MultihostRole | MultihostHost, where: str) -> None:
Expand Down Expand Up @@ -1235,7 +1236,7 @@ def mh_utility_exit_dependencies(obj: MultihostRole | MultihostHost, where: str)
errors.append(e)

if errors:
raise Exception(errors)
raise TeardownExceptionGroup("Unable to exit some utilities (util.__exit__)", errors)


def mh_utility_pytest_report_teststatus(
Expand Down
7 changes: 5 additions & 2 deletions pytest_mh/_private/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from .artifacts import MultihostArtifactsCollectable, MultihostArtifactsType
from .data import MultihostItemData
from .errors import TeardownExceptionGroup
from .fixtures import MultihostFixture
from .logging import MultihostLogger
from .marks import TopologyMark
Expand Down Expand Up @@ -660,7 +661,7 @@ def _teardown_hosts(self, hosts: list[MultihostHost]) -> None:
self.multihost.logger.flush(outcome, f"hosts/{host.hostname}/pytest_teardown.log")

if errors:
raise Exception(errors)
raise TeardownExceptionGroup("Unable to teardown some hosts (host.pytest_teardown)", errors)

def _setup_topology(self, name: str, controller: TopologyController) -> None:
# Silent mypy false positive
Expand Down Expand Up @@ -724,7 +725,9 @@ def _teardown_topology(self, name: str, controller: TopologyController) -> None:
controller.logger.phase(f"TOPOLOGY TEARDOWN EXIT HOST UTILS DONE :: {name}")

if errors:
raise Exception(errors)
raise TeardownExceptionGroup(
"Unable to teardown topology (topology_controller.topology_teardown)", errors
)

outcome = "passed"
finally:
Expand Down

0 comments on commit 51cc9d9

Please sign in to comment.