From b50643814bc96f1878439e0bc0aebfcc4e5bdf15 Mon Sep 17 00:00:00 2001 From: Callum Sherry Date: Wed, 15 Jul 2026 14:39:53 -0700 Subject: [PATCH] Handle missing session metadata errors --- tests/test_utils.py | 66 +++++++++++++++++++++++++++++++++++++++++++++ utils.py | 10 ++++--- 2 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/test_utils.py diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 00000000..aae762f8 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,66 @@ +import os +import sys +from unittest.mock import patch + +import pytest + + +thisDir = os.path.dirname(os.path.realpath(__file__)) +repoDir = os.path.abspath(os.path.join(thisDir,'../')) +sys.path.append(repoDir) +from utils import getCalibration, getNeutralTrialID + + +@patch('utils.getSessionJson') +def test_get_neutral_trial_id_from_session_trial(mock_get_session): + mock_get_session.return_value = { + 'trials': [ + {'id': 'dynamic-id', 'name': 'squats'}, + {'id': 'neutral-id', 'name': 'neutral'}, + ], + 'meta': {}, + } + + assert getNeutralTrialID('session-id') == 'neutral-id' + + +@patch('utils.getSessionJson') +def test_get_neutral_trial_id_from_metadata_fallback(mock_get_session): + mock_get_session.return_value = { + 'trials': [ + {'id': 'dynamic-id', 'name': 'squats'}, + ], + 'meta': { + 'neutral_trial': {'id': 'metadata-neutral-id'}, + }, + } + + assert getNeutralTrialID('session-id') == 'metadata-neutral-id' + + +@patch('utils.getSessionJson') +def test_get_neutral_trial_id_raises_clear_error_without_neutral_trial(mock_get_session): + mock_get_session.return_value = { + 'trials': [ + {'id': 'dynamic-id', 'name': 'squats'}, + ], + 'meta': {}, + } + + with pytest.raises(Exception, match='No neutral trial in session'): + getNeutralTrialID('session-id') + + +@patch('utils.getTrialJson') +@patch('utils.getCalibrationTrialID') +def test_get_calibration_raises_clear_error_without_camera_mapping( + mock_get_calibration_trial_id, mock_get_trial): + mock_get_calibration_trial_id.return_value = 'calibration-id' + mock_get_trial.return_value = { + 'results': [ + {'tag': 'calibration_parameters', 'media': 'calibration-url'}, + ], + } + + with pytest.raises(Exception, match='Redo calibration before processing dynamic trials'): + getCalibration('session-id', '/tmp/session') diff --git a/utils.py b/utils.py index 962aa74b..e7cca36b 100644 --- a/utils.py +++ b/utils.py @@ -855,10 +855,11 @@ def getNeutralTrialID(session_id): if len(neutral_ids)>0: neutralID = neutral_ids[-1] - elif session['meta']['neutral_trial']: - neutralID = session['meta']['neutral_trial']['id'] else: - raise Exception('No neutral trial in session.') + neutral_trial = (session.get('meta') or {}).get('neutral_trial') + if not neutral_trial: + raise Exception('No neutral trial in session.') + neutralID = neutral_trial['id'] return neutralID @@ -893,6 +894,8 @@ def getCalibration(session_id,session_path,trial_type='dynamic',getCalibrationOp # download the mapping videoFolder = os.path.join(session_path,'Videos') os.makedirs(videoFolder, exist_ok=True) + if 'camera_mapping' not in calibResultTags: + raise Exception('Calibration is missing camera mapping results. Redo calibration before processing dynamic trials.') mapURL = trial['results'][calibResultTags.index('camera_mapping')]['media'] mapLocalPath = os.path.join(videoFolder,'mappingCamDevice.pickle') download_file(mapURL,mapLocalPath) @@ -2121,4 +2124,3 @@ def makeRequestWithRetry(method, url, files=files) response.raise_for_status() return response -