Skip to content

Commit be4402b

Browse files
committed
feat: add error handling for validation of class files in score calibration creation and modification
1 parent 33d78cd commit be4402b

File tree

2 files changed

+28
-15
lines changed

2 files changed

+28
-15
lines changed

src/mavedb/routers/score_calibrations.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from mavedb.lib.score_sets import csv_data_to_df
2727
from mavedb.lib.validation.constants.general import calibration_class_column_name, calibration_variant_column_name
2828
from mavedb.lib.validation.dataframe.calibration import validate_and_standardize_calibration_classes_dataframe
29+
from mavedb.lib.validation.exceptions import ValidationError
2930
from mavedb.models.score_calibration import ScoreCalibration
3031
from mavedb.models.score_set import ScoreSet
3132
from mavedb.view_models import score_calibration
@@ -290,10 +291,16 @@ async def create_score_calibration_route(
290291
status_code=400, detail=f"Error decoding file: {e}. Ensure the file has correct values."
291292
)
292293

293-
standardized_classes_df = validate_and_standardize_calibration_classes_dataframe(
294-
db, score_set, calibration, classes_df
295-
)
296-
variant_classes = variant_classification_df_to_dict(standardized_classes_df)
294+
try:
295+
standardized_classes_df = validate_and_standardize_calibration_classes_dataframe(
296+
db, score_set, calibration, classes_df
297+
)
298+
variant_classes = variant_classification_df_to_dict(standardized_classes_df)
299+
except ValidationError as e:
300+
raise HTTPException(
301+
status_code=422,
302+
detail=[{"loc": [e.custom_loc or "classesFile"], "msg": str(e), "type": "value_error"}],
303+
)
297304

298305
created_calibration = await create_score_calibration_in_score_set(
299306
db, calibration, user_data.user, variant_classes if classes_file else None
@@ -438,10 +445,16 @@ async def modify_score_calibration_route(
438445
status_code=400, detail=f"Error decoding file: {e}. Ensure the file has correct values."
439446
)
440447

441-
standardized_classes_df = validate_and_standardize_calibration_classes_dataframe(
442-
db, score_set, calibration_update, classes_df
443-
)
444-
variant_classes = variant_classification_df_to_dict(standardized_classes_df)
448+
try:
449+
standardized_classes_df = validate_and_standardize_calibration_classes_dataframe(
450+
db, score_set, calibration_update, classes_df
451+
)
452+
variant_classes = variant_classification_df_to_dict(standardized_classes_df)
453+
except ValidationError as e:
454+
raise HTTPException(
455+
status_code=422,
456+
detail=[{"loc": [e.custom_loc or "classesFile"], "msg": str(e), "type": "value_error"}],
457+
)
445458

446459
updated_calibration = await modify_score_calibration(
447460
db, item, calibration_update, user_data.user, variant_classes if classes_file else None

tests/validation/dataframe/test_calibration.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ def test_validate_and_standardize_calibration_classes_dataframe_success(self, mo
8080
mock_dependencies["validate_data_column"].assert_called_once()
8181

8282
def test_validate_and_standardize_calibration_classes_dataframe_not_class_based(self):
83-
"""Test ValueError when calibration is not class-based."""
83+
"""Test ValidationError when calibration is not class-based."""
8484
mock_db = Mock()
8585
mock_score_set = Mock()
8686
mock_calibration = Mock()
8787
mock_calibration.class_based = False
8888
input_df = pd.DataFrame({"variant": ["var1"], "class": ["A"]})
8989

9090
with pytest.raises(
91-
ValueError,
91+
ValidationError,
9292
match="Calibration classes file can only be provided for functional classification calibrations.",
9393
):
9494
validate_and_standardize_calibration_classes_dataframe(mock_db, mock_score_set, mock_calibration, input_df)
@@ -170,7 +170,7 @@ def test_validate_and_standardize_calibration_classes_dataframe_invalid_classes(
170170
mock_calibration.functional_classifications = None
171171

172172
with pytest.raises(
173-
ValueError, match="Calibration must have functional classifications defined for class validation."
173+
ValidationError, match="Calibration must have functional classifications defined for class validation."
174174
):
175175
validate_and_standardize_calibration_classes_dataframe(mock_db, mock_score_set, mock_calibration, input_df)
176176

@@ -634,24 +634,24 @@ def test_validate_calibration_classes_success(self):
634634
validate_calibration_classes(calibration, classes)
635635

636636
def test_validate_calibration_classes_no_functional_classifications(self):
637-
"""Test ValueError when calibration has no functional classifications."""
637+
"""Test ValidationError when calibration has no functional classifications."""
638638
calibration = Mock(spec=score_calibration.ScoreCalibrationCreate)
639639
calibration.functional_classifications = None
640640
classes = pd.Series(["class_a", "class_b"])
641641

642642
with pytest.raises(
643-
ValueError, match="Calibration must have functional classifications defined for class validation."
643+
ValidationError, match="Calibration must have functional classifications defined for class validation."
644644
):
645645
validate_calibration_classes(calibration, classes)
646646

647647
def test_validate_calibration_classes_empty_functional_classifications(self):
648-
"""Test ValueError when calibration has empty functional classifications."""
648+
"""Test ValidationError when calibration has empty functional classifications."""
649649
calibration = Mock(spec=score_calibration.ScoreCalibrationCreate)
650650
calibration.functional_classifications = []
651651
classes = pd.Series(["class_a", "class_b"])
652652

653653
with pytest.raises(
654-
ValueError, match="Calibration must have functional classifications defined for class validation."
654+
ValidationError, match="Calibration must have functional classifications defined for class validation."
655655
):
656656
validate_calibration_classes(calibration, classes)
657657

0 commit comments

Comments
 (0)