Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed error message omission during Lab execution #53

Merged
merged 1 commit into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed
- Fixed readthedocs.org documentation build now requiring a .readthedocs.yaml config file
- Fixed a bug where the actual error message from an exception happening during execution through a `Lab` instance would
be omitted


## [0.3.0] - 2024-04-23
Expand Down
7 changes: 5 additions & 2 deletions alkymi/lab.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ def _add_user_args_(self, parser: argparse.ArgumentParser, args: Dict[str, Arg])
@staticmethod
def _remove_alkymi_internals_from_traceback(e: Exception, num_stack_frames_to_omit: int) -> str:
"""

Remove parts of the stack trace internal to alkymi to create a shorter and less noisy error message. Will
prepend the current call stack to accurately present the whole exception as though it had bubbled all the way
up to the caller

:param e: The exception to load the traceback from
:param num_stack_frames_to_omit: A number of stack frames to omit - can be used to e.g. ignore this call on the
Expand Down Expand Up @@ -182,7 +184,8 @@ def _remove_alkymi_internals_from_traceback(e: Exception, num_stack_frames_to_om
# Finally, combine the stack with an "omitted" statement and the filtered traceback
return "".join(stack.format()) + \
" <alkymi internals omitted...>\n" + \
"".join(traceback.StackSummary.from_list(filtered_frames).format())
"".join(traceback.StackSummary.from_list(filtered_frames).format()) + \
"".join(traceback.format_exception_only(type(e), value=e))

def __repr__(self) -> str:
"""
Expand Down
8 changes: 6 additions & 2 deletions tests/test_lab.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python
import io
import time
from typing import List

import pytest
Expand Down Expand Up @@ -187,9 +188,11 @@ def test_lab_omits_alkymi_internals_in_traceback(capsys: pytest.CaptureFixture)
"""

# Create a lab containing a single recipe that will raise on execution
expected_error_message = f"Failure @ {time.time()}"

@alk.recipe()
def fail() -> None:
raise RuntimeError("Failure")
raise RuntimeError(expected_error_message)

lab = alk.Lab("failure lab")
lab.add_recipe(fail)
Expand All @@ -206,7 +209,8 @@ def fail() -> None:
assert 'lab.brew(fail)' in printed_error # The lab invocation that led to the failure
assert '<alkymi internals omitted...>' in printed_error # A statement that alkymi internals were omitted
assert 'in fail' in printed_error # The recipe (function) that failed
assert 'raise RuntimeError("Failure")' in printed_error # The line that failed
assert 'RuntimeError(expected_error_message)' in printed_error # The line that failed
assert f"RuntimeError: {expected_error_message}" in printed_error # The actual error message

# The traceback should not contain the following:
assert 'alkymi/core.py' not in printed_error # Any line related to the internal execution engine of alkymi
Loading