Skip to content

Commit

Permalink
update l2ss exception
Browse files Browse the repository at this point in the history
  • Loading branch information
sliu008 committed Dec 31, 2024
1 parent 0223144 commit d962cea
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 2 deletions.
16 changes: 14 additions & 2 deletions podaac/subsetter/subset_harmony.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from tempfile import mkdtemp
import traceback
from typing import List, Union
import sys

import pystac
from pystac import Asset
Expand All @@ -41,9 +42,16 @@


class L2SSException(HarmonyException):
"""Base class for exceptions in the Harmony GDAL Adapter."""

"""L2SS Exception class for custom error messages to see in harmony api calls."""
def __init__(self, original_exception):
# Ensure we can extract traceback information
if original_exception.__traceback__ is None:
# Capture the current traceback if not already present
try:
raise original_exception
except type(original_exception):
original_exception.__traceback__ = sys.exc_info()[2]

# Extract the last traceback entry (most recent call) for the error location
tb = traceback.extract_tb(original_exception.__traceback__)[-1]

Expand All @@ -57,8 +65,12 @@ def __init__(self, original_exception):
readable_message = (f"Error in file '{filename}', line {lineno}, in function '{funcname}': "
f"{error_msg}")

# Call the parent class constructor with the formatted message and category
super().__init__(readable_message, 'podaac/l2-subsetter')

# Store the original exception for potential further investigation
self.original_exception = original_exception


def podaac_to_harmony_bbox(bbox: np.ndarray) -> Union[np.ndarray, float]:
"""
Expand Down
97 changes: 97 additions & 0 deletions tests/test_l2ss_py_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import pytest
import traceback
import sys
from podaac.subsetter.subset_harmony import L2SSException


def test_exception_message_formatting():
"""
Test that the L2SSException correctly formats the error message
with file, line, function, and original error details.
"""
try:
# Simulate an error by intentionally causing a division by zero
1 / 0
except ZeroDivisionError as original_error:
l2ss_exception = L2SSException(original_error)

# Detailed assertions with informative error messages
error_str = str(l2ss_exception)
error_msg = l2ss_exception.message

assert "Error in file" in error_msg, f"Expected file context, got: {error_msg}"
assert "line" in error_msg, f"Expected line number, got: {error_msg}"
assert "in function" in error_msg, f"Expected function context, got: {error_msg}"
assert "division by zero" in error_msg, f"Expected original error message, got: {error_msg}"
assert l2ss_exception.category == 'podaac/l2-subsetter'

def test_exception_traceback_details():
"""
Verify that the exception captures the correct traceback information.
"""
def inner_function():
# Another function to add depth to the traceback
1 / 0

try:
inner_function()
except ZeroDivisionError as original_error:
l2ss_exception = L2SSException(original_error)

# Extract expected details
tb = traceback.extract_tb(original_error.__traceback__)[-1]
expected_filename = tb.filename
expected_lineno = tb.lineno
expected_funcname = tb.name

error_msg = l2ss_exception.message
assert expected_filename in error_msg, f"Filename not found, got: {error_msg}"
assert str(expected_lineno) in error_msg, f"Line number not found, got: {error_msg}"
assert expected_funcname in error_msg, f"Function name not found, got: {error_msg}"

def test_original_error_type_preservation():
"""
Ensure that the original error type is preserved in the traceback.
"""
try:
raise ValueError("Test error message")
except ValueError as original_error:
l2ss_exception = L2SSException(original_error)

error_msg = l2ss_exception.message
assert "Test error message" in error_msg, f"Original error message not found, got: {error_msg}"
assert isinstance(l2ss_exception.original_exception, ValueError)

def test_module_identifier():
"""
Verify that the module identifier is set correctly.
"""
try:
raise RuntimeError("Sample error")
except RuntimeError as original_error:
l2ss_exception = L2SSException(original_error)

assert l2ss_exception.category == 'podaac/l2-subsetter'

def test_exception_with_no_traceback():
"""
Test handling of an exception without an existing traceback.
"""
# Create an exception without a traceback
try:
raise ValueError("Test exception without traceback")
except ValueError as original_error:
# Deliberately remove the traceback
original_error.__traceback__ = None

# Create L2SSException
l2ss_exception = L2SSException(original_error)

# Verify that a traceback was generated
assert l2ss_exception.original_exception is not None

# Check that the message is still formatted
error_msg = l2ss_exception.message
assert "Error in file" in error_msg
assert "in function" in error_msg
assert "Test exception without traceback" in error_msg

0 comments on commit d962cea

Please sign in to comment.