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

handle exceptions which have no message #370

Merged
merged 3 commits into from
Jun 29, 2023
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
7 changes: 6 additions & 1 deletion src/seedsigner/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,12 @@ def handle_exception(self, e) -> Destination:
# So we extract the Exception type and trim off any "foo.bar." namespacing:
last_line = traceback.format_exc().splitlines()[-1]
exception_type = last_line.split(":")[0].split(".")[-1]
exception_msg = last_line.split(":")[1]

# Extract the error message, if there is one
if ":" in last_line:
jdlcdl marked this conversation as resolved.
Show resolved Hide resolved
exception_msg = last_line.split(":")[1]
else:
exception_msg = ""

# Scan for the last debugging line that includes a line number reference
line_info = None
Expand Down
42 changes: 42 additions & 0 deletions tests/test_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,48 @@ def test_singleton_get_instance_preserves_state(reset_controller):
assert controller.unverified_address == "123abc"


def test_handle_exception(reset_controller):
""" Handle exceptions that get caught by the controller """

def process_exception_asserting_valid_error(exception_type, exception_msg=None):
"""
Exceptions caught by the controller are forwarded to the
UnhandledExceptionView with view_args["error"] being a list
of three strings, ie: [exception_type, line_info, exception_msg]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I LOVE that you explained the format here!

@bitcoinprecept We can drop a super low-priority TODO pin on that error obj to define it as a proper class someday. It's obviously a bit fragile in the current approach (that was my bad design). Would be a good first issue for a beginner.
see:

error = [
exception_type,
line_info,
exception_msg,
]

"""
try:
if exception_msg:
raise exception_type(exception_msg)
else:
raise exception_type()
except Exception as e:
error = controller.handle_exception(e).view_args["error"]

# assert that error structure is valid
assert len(error) == 3
assert error[0] in str(exception_type)
assert type(error[1]) == str
if exception_msg:
assert exception_msg in error[2]
else:
assert error[2] == ""

# Initialize the controller
controller = Controller.get_instance()

exception_tests = [
# exceptions with an exception_msg
(Exception, "foo"),
(KeyError, "key not found"),
# exceptions without an exception_msg
(Exception, ""),
(Exception, None),
]

for exception_type, exception_msg in exception_tests:
process_exception_asserting_valid_error(exception_type, exception_msg)


def test_missing_settings_get_defaults(reset_controller):
""" Should gracefully handle all missing fields from `settings.json` """

Expand Down