From d7b4e76b020dc732606c0a507c4420c8b3cf9045 Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Fri, 20 Mar 2026 14:39:51 +0530 Subject: [PATCH 1/3] fix circular import and view results --- backend/app/core/batch/client.py | 2 +- backend/app/crud/tts_evaluations/result.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/app/core/batch/client.py b/backend/app/core/batch/client.py index dd25911d1..115df6217 100644 --- a/backend/app/core/batch/client.py +++ b/backend/app/core/batch/client.py @@ -6,7 +6,7 @@ from google import genai from sqlmodel import Session -from app.core.exception_handlers import HTTPException +from fastapi import HTTPException from app.crud.credentials import get_provider_credential logger = logging.getLogger(__name__) diff --git a/backend/app/crud/tts_evaluations/result.py b/backend/app/crud/tts_evaluations/result.py index b13b5a62e..6ebf872ab 100644 --- a/backend/app/crud/tts_evaluations/result.py +++ b/backend/app/crud/tts_evaluations/result.py @@ -133,7 +133,9 @@ def get_results_by_run_id( results = [] for result in rows: signed_url = ( - storage.get_signed_url(result.object_store_url) if storage else None + storage.get_signed_url(result.object_store_url) + if storage and result.object_store_url + else None ) results.append(TTSResultPublic.from_model(result, signed_url=signed_url)) From 29b76bc07bcdf07d05308f844774b2784dbb6dbe Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Fri, 20 Mar 2026 15:14:45 +0530 Subject: [PATCH 2/3] added testcases for failed samples in TTS --- .../tests/api/routes/test_tts_evaluation.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/backend/app/tests/api/routes/test_tts_evaluation.py b/backend/app/tests/api/routes/test_tts_evaluation.py index b3409734c..13d77e219 100644 --- a/backend/app/tests/api/routes/test_tts_evaluation.py +++ b/backend/app/tests/api/routes/test_tts_evaluation.py @@ -1006,6 +1006,76 @@ def test_get_run_with_results( assert "Hello world" in texts assert "Good morning" in texts + @patch("app.api.routes.tts_evaluations.evaluation.get_cloud_storage") + def test_get_run_with_signed_urls_and_null_object_store_url( + self, + mock_get_cloud_storage: MagicMock, + client: TestClient, + user_api_key_header: dict[str, str], + db: Session, + user_api_key: TestAuthContext, + test_dataset_with_samples: EvaluationDataset, + ) -> None: + """Test that signed URL generation handles results with null object_store_url.""" + dataset = test_dataset_with_samples + + mock_storage = MagicMock() + mock_storage.get_signed_url.return_value = ( + "https://signed-url.example.com/audio.wav" + ) + mock_get_cloud_storage.return_value = mock_storage + + run = create_tts_run( + session=db, + run_name="signed_url_null_test", + dataset_id=dataset.id, + dataset_name=dataset.name, + org_id=user_api_key.organization_id, + project_id=user_api_key.project_id, + models=["gemini-2.5-pro-preview-tts"], + total_items=2, + ) + + # Result with valid S3 URL + create_test_tts_result( + db=db, + evaluation_run_id=run.id, + organization_id=user_api_key.organization_id, + project_id=user_api_key.project_id, + sample_text="Completed result", + status=JobStatus.SUCCESS.value, + object_store_url="s3://bucket/audio/test.wav", + ) + # Result with null object_store_url (failed) + create_test_tts_result( + db=db, + evaluation_run_id=run.id, + organization_id=user_api_key.organization_id, + project_id=user_api_key.project_id, + sample_text="Failed result", + status=JobStatus.FAILED.value, + object_store_url=None, + ) + + response = client.get( + f"/api/v1/evaluations/tts/runs/{run.id}", + params={"include_results": True, "include_signed_url": True}, + headers=user_api_key_header, + ) + + assert response.status_code == 200, response.text + data = response.json()["data"] + assert data["results_total"] == 2 + + results_by_text = {r["sample_text"]: r for r in data["results"]} + assert results_by_text["Completed result"]["signed_url"] is not None + assert results_by_text["Failed result"]["signed_url"] is None + + # get_signed_url should only be called for the result with a valid URL + mock_storage.get_signed_url.assert_called_once_with( + "s3://bucket/audio/test.wav" + ) + def test_get_run_without_results( self, client: TestClient, From 2a8b81bf45ca6d153acb1963ad1bb3878ea51f1a Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Fri, 20 Mar 2026 15:22:58 +0530 Subject: [PATCH 3/3] cleanup --- backend/app/tests/api/routes/test_tts_evaluation.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backend/app/tests/api/routes/test_tts_evaluation.py b/backend/app/tests/api/routes/test_tts_evaluation.py index 13d77e219..0a8810c04 100644 --- a/backend/app/tests/api/routes/test_tts_evaluation.py +++ b/backend/app/tests/api/routes/test_tts_evaluation.py @@ -1071,11 +1071,6 @@ def test_get_run_with_signed_urls_and_null_object_store_url( assert results_by_text["Completed result"]["signed_url"] is not None assert results_by_text["Failed result"]["signed_url"] is None - # get_signed_url should only be called for the result with a valid URL - mock_storage.get_signed_url.assert_called_once_with( - "s3://bucket/audio/test.wav" - ) - def test_get_run_without_results( self, client: TestClient,