Skip to content

Commit

Permalink
fixups to get api tests passing and add context
Browse files Browse the repository at this point in the history
  • Loading branch information
sfoster1 committed Jun 20, 2023
1 parent d47f58e commit ee9f055
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 30 deletions.
3 changes: 1 addition & 2 deletions api/src/opentrons/protocol_runner/legacy_command_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from collections import defaultdict
from datetime import datetime
from typing import Dict, List, Optional, Tuple, Union
from traceback import format_exception, format_exception_only

from opentrons_shared_data.pipette.dev_types import PipetteNameType
from opentrons.types import MountType, DeckSlotName, Location
Expand Down Expand Up @@ -60,7 +59,7 @@ def __init__(self, wrapping_exc: BaseException) -> None:
super().__init__(
code=ErrorCodes.GENERAL_ERROR,
message=str(wrapping_exc),
wrapping=[PythonException(wrapping_exc)]
wrapping=[PythonException(wrapping_exc)],
)


Expand Down
6 changes: 4 additions & 2 deletions api/src/opentrons/protocols/execution/errors.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from opentrons_shared_data.errors.exceptions import GeneralError, PythonException
from opentrons_shared_data.errors.exceptions import GeneralError


class ExceptionInProtocolError(GeneralError):
"""This exception wraps an exception that was raised from a protocol
Expand All @@ -17,7 +18,8 @@ def __init__(self, original_exc, original_tb, message, line):
self.original_exc.__class__.__name__,
" [line {}]".format(self.line) if self.line else "",
self.message,
))
),
)

def __str__(self):
return self.message
28 changes: 8 additions & 20 deletions api/tests/opentrons/protocol_engine/state/test_command_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -830,29 +830,17 @@ def test_command_store_saves_unknown_finish_error() -> None:
# and they wrap
wrappedErrors=[
errors.ErrorOccurrence(
# the wrapped error(s) have the same id and creation time
id="error-id",
createdAt=datetime(year=2021, month=1, day=1),
# but the details of the wrapped exception
errorType="GeneralError",
detail="Error 4000 GENERAL_ERROR (GeneralError)",
errorType="PythonException",
detail="RuntimeError: oh no\n",
errorCode="4000",
# including further wrapped errors
wrappedErrors=[
errors.ErrorOccurrence(
id="error-id",
createdAt=datetime(year=2021, month=1, day=1),
errorType="PythonException",
detail="RuntimeError: oh no\n",
errorCode="4000",
# and we get some fun extra info if this wraps a normal exception
errorInfo={
"class": "RuntimeError",
"args": "('oh no',)",
},
wrappedErrors=[],
)
],
# and we get some fun extra info if this wraps a normal exception
errorInfo={
"class": "RuntimeError",
"args": "('oh no',)",
},
wrappedErrors=[],
)
],
)
Expand Down
10 changes: 8 additions & 2 deletions shared-data/python/opentrons_shared_data/errors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@

from .categories import ErrorCategories, ErrorCategory
from .codes import ErrorCodes, ErrorCode
from .exceptions import EnumeratedError, PythonException, GeneralError, RoboticsControlError, RoboticsInteractionError
from .exceptions import (
EnumeratedError,
PythonException,
GeneralError,
RoboticsControlError,
RoboticsInteractionError,
)

__all__ = [
"ErrorCategory",
Expand All @@ -20,5 +26,5 @@
"PythonException",
"GeneralError",
"RoboticsControlError",
"RoboticsInteractionError"
"RoboticsInteractionError",
]
8 changes: 5 additions & 3 deletions shared-data/python/opentrons_shared_data/errors/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ def __init__(self, exc: BaseException) -> None:
"""Build a PythonException."""

def _descend_exc_ctx(exc: BaseException) -> List[PythonException]:
descendants: List[PythonException] = []
if exc.__context__:
descendants.append(PythonException(exc.__context__))
if exc.__cause__:
return [PythonException(exc.__cause__)]
else:
return []
descendants.append(PythonException(exc.__cause__))
return descendants

base_details = {
k: str(v)
Expand Down
21 changes: 20 additions & 1 deletion shared-data/python/tests/errors/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def _raise_inner() -> None:


def test_exception_wrapping_rethrow() -> None:
"""We can even wrap exceptions inside an except."""
"""We can wrap raise-froms."""
try:
try:
raise RuntimeError("oh no!")
Expand All @@ -53,3 +53,22 @@ def test_exception_wrapping_rethrow() -> None:
assert wrapped.detail["class"] == "RuntimeError"
assert wrapped.detail["traceback"]
assert wrapped.detail["args"] == "('oh no!',)"


def test_exception_wrapping_error_in_except() -> None:
"""We can even wrap exceptions in exception handlers."""
try:
try:
raise RuntimeError("oh no!")
except RuntimeError:
raise KeyError("uh oh")
except BaseException as e:
wrapped = PythonException(e)

# when we have an exception-during-handler, the originally-handled
# exception is what's bubbled up:
assert wrapped.detail["class"] == "KeyError"
assert len(wrapped.wrapping) == 1
assert wrapped.wrapping[0].detail["class"] == "RuntimeError"
assert wrapped.wrapping[0].detail["traceback"]
assert wrapped.wrapping[0].detail["args"] == "('oh no!',)"

0 comments on commit ee9f055

Please sign in to comment.