diff --git a/openagent_eval/exceptions/cli.py b/openagent_eval/exceptions/cli.py index 6ab4216..caf9503 100644 --- a/openagent_eval/exceptions/cli.py +++ b/openagent_eval/exceptions/cli.py @@ -87,9 +87,9 @@ def __init__( details: Additional context about the error. """ error_details = details or {} - if field: + if field is not None: error_details["field"] = field - if value: + if value is not None: error_details["value"] = value super().__init__(message=message, command=command, details=error_details) diff --git a/openagent_eval/exceptions/dataset.py b/openagent_eval/exceptions/dataset.py index c7ac9d8..0663936 100644 --- a/openagent_eval/exceptions/dataset.py +++ b/openagent_eval/exceptions/dataset.py @@ -81,7 +81,7 @@ def __init__( error_details = details or {} if data_format: error_details["format"] = data_format - if line_number: + if line_number is not None: error_details["line_number"] = line_number super().__init__(message=message, dataset_path=dataset_path, details=error_details) diff --git a/tests/unit/test_exceptions.py b/tests/unit/test_exceptions.py index cb3747e..309c1f2 100644 --- a/tests/unit/test_exceptions.py +++ b/tests/unit/test_exceptions.py @@ -90,6 +90,20 @@ def test_invalid_dataset_error(self) -> None: assert error.data_format == "json" assert error.line_number == 10 + def test_invalid_dataset_error_preserves_zero_line_number(self) -> None: + """Test that line_number=0 is retained in error details and str representation.""" + error = InvalidDatasetError("Invalid line", line_number=0) + assert error.line_number == 0 + assert error.details["line_number"] == 0 + assert "line_number=0" in str(error) + + def test_invalid_dataset_error_omits_none_line_number(self) -> None: + """Test that line_number=None is excluded from error details.""" + error = InvalidDatasetError("Invalid format", data_format="json") + assert error.line_number is None + assert "line_number" not in error.details + assert "line_number" not in str(error) + def test_validation_error(self) -> None: """Test dataset validation error.""" error = DatasetValidationError( @@ -129,6 +143,14 @@ def test_timeout_error_preserves_zero_timeout(self) -> None: error = MetricTimeoutError("Timed out immediately", timeout_seconds=0.0) assert error.timeout_seconds == 0.0 assert error.details["timeout_seconds"] == 0.0 + assert "timeout_seconds=0.0" in str(error) + + def test_timeout_error_omits_none_timeout(self) -> None: + """Test that timeout_seconds=None is excluded from error details.""" + error = MetricTimeoutError("Timed out") + assert error.timeout_seconds is None + assert "timeout_seconds" not in error.details + assert "timeout_seconds" not in str(error) class TestDiagnosisError: @@ -236,3 +258,23 @@ def test_validation_error(self) -> None: error = ValidationError("Invalid input", field="config_path", value="missing.yaml") assert error.field == "config_path" assert error.value == "missing.yaml" + + def test_validation_error_preserves_empty_string_field_and_value(self) -> None: + """Test that empty string field and value are retained in error details and str representation.""" + error = ValidationError("Validation failed", field="", value="") + assert error.field == "" + assert error.value == "" + assert error.details["field"] == "" + assert error.details["value"] == "" + assert "field=" in str(error) + assert "value=" in str(error) + + def test_validation_error_omits_none_field_and_value(self) -> None: + """Test that field=None and value=None are excluded from error details.""" + error = ValidationError("Validation failed") + assert error.field is None + assert error.value is None + assert "field" not in error.details + assert "value" not in error.details + assert "field" not in str(error) + assert "value" not in str(error)