Skip to content

Commit 8f94eb6

Browse files
remote/client: prepare handling of multiple Errors
A future commit will introduce ClientSession code that needs to handle multiple Error exceptions, aggregated into a dedicated group. Python 3.11 introduced support for exception groups [1]. This allows raising multiple exceptions (not caused by one another) while keeping their individual tracebacks etc. intact (i.e. `labgrid-client -d` will still show all individual tracebacks). Since labgrid will drop Python 3.10 support in October 2026 earliest, use the backported version of exception groups until then. While at it, add a Error.__str__() method, so Error and ErrorGroup can use the same print to stderr statement in the except clause. [1] https://docs.python.org/3/library/exceptions.html#exception-groups Signed-off-by: Bastian Krause <bst@pengutronix.de>
1 parent 3b5d269 commit 8f94eb6

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

labgrid/remote/client.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
import attr
2929
import grpc
3030

31+
# TODO: drop if Python >= 3.11 guaranteed
32+
from exceptiongroup import ExceptionGroup # pylint: disable=redefined-builtin
33+
3134
from .common import (
3235
ResourceEntry,
3336
ResourceMatch,
@@ -57,7 +60,8 @@
5760

5861

5962
class Error(Exception):
60-
pass
63+
def __str__(self):
64+
return f"Error: {' '.join(self.args)}"
6165

6266

6367
class UserError(Error):
@@ -72,6 +76,13 @@ class InteractiveCommandError(Error):
7276
pass
7377

7478

79+
class ErrorGroup(ExceptionGroup):
80+
def __str__(self):
81+
# TODO: drop pylint disable once https://github.com/pylint-dev/pylint/issues/8985 is fixed
82+
errors_combined = "\n".join(f"- {' '.join(e.args)}" for e in self.exceptions) # pylint: disable=not-an-iterable
83+
return f"{self.message}:\n{errors_combined}"
84+
85+
7586
@attr.s(eq=False)
7687
class ClientSession:
7788
"""The ClientSession encapsulates all the actions a Client can invoke on
@@ -2212,11 +2223,11 @@ def main():
22122223
if args.debug:
22132224
traceback.print_exc(file=sys.stderr)
22142225
exitcode = e.exitcode
2215-
except Error as e:
2226+
except (Error, ErrorGroup) as e:
22162227
if args.debug:
22172228
traceback.print_exc(file=sys.stderr)
22182229
else:
2219-
print(f"{parser.prog}: error: {e}", file=sys.stderr)
2230+
print(f"{parser.prog}: {e}", file=sys.stderr)
22202231
exitcode = 1
22212232
except KeyboardInterrupt:
22222233
exitcode = 1

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ classifiers = [
3333
]
3434
dependencies = [
3535
"attrs>=21.4.0",
36+
"exceptiongroup>=1.3.0", # TODO: drop if Python >= 3.11 guaranteed
3637
"grpcio>=1.64.1, <2.0.0",
3738
"grpcio-reflection>=1.64.1, <2.0.0",
3839
"protobuf>=5.27.0",

0 commit comments

Comments
 (0)