From 0e2b5a2d58cb4fd6060027fa6099f639d880b9d1 Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Wed, 11 Mar 2026 11:04:34 +0530 Subject: [PATCH 1/5] tts cleanups --- .../app/api/routes/stt_evaluations/dataset.py | 13 +++------- .../api/routes/tts_evaluations/evaluation.py | 11 ++++++++ .../app/api/routes/tts_evaluations/result.py | 17 +++++++++++-- backend/app/core/cloud/storage.py | 25 +++++++++++++++++++ backend/app/crud/stt_evaluations/result.py | 11 +++----- backend/app/crud/tts_evaluations/cron.py | 4 ++- backend/app/crud/tts_evaluations/result.py | 10 +++++++- backend/app/models/tts_evaluation.py | 9 ++++++- 8 files changed, 78 insertions(+), 22 deletions(-) diff --git a/backend/app/api/routes/stt_evaluations/dataset.py b/backend/app/api/routes/stt_evaluations/dataset.py index ca3dbde51..c6afc8d82 100644 --- a/backend/app/api/routes/stt_evaluations/dataset.py +++ b/backend/app/api/routes/stt_evaluations/dataset.py @@ -168,15 +168,10 @@ def get_dataset( samples = [] for s in sample_records: signed_url = None - if include_signed_url and storage and s.file_id in file_map: - try: - signed_url = storage.get_signed_url( - file_map.get(s.file_id).object_store_url - ) - except Exception as e: - logger.warning( - f"[get_dataset] Failed to generate signed URL for file_id {s.file_id}: {e}" - ) + if storage and s.file_id in file_map: + signed_url = storage.get_signed_url_or_none( + file_map[s.file_id].object_store_url + ) samples.append( STTSamplePublic( diff --git a/backend/app/api/routes/tts_evaluations/evaluation.py b/backend/app/api/routes/tts_evaluations/evaluation.py index ff073c5cb..8c85f0296 100644 --- a/backend/app/api/routes/tts_evaluations/evaluation.py +++ b/backend/app/api/routes/tts_evaluations/evaluation.py @@ -8,6 +8,7 @@ from app.api.deps import AuthContextDep, SessionDep from app.api.permissions import Permission, require_permission from app.celery.utils import start_low_priority_job +from app.core.cloud import get_cloud_storage from app.crud.tts_evaluations import ( create_tts_run, get_results_by_run_id, @@ -169,6 +170,9 @@ def get_tts_evaluation_run( auth_context: AuthContextDep, run_id: int, include_results: bool = Query(True, description="Include results in response"), + include_signed_url: bool = Query( + False, description="Include signed URLs for generated audio files" + ), ) -> APIResponse[TTSEvaluationRunWithResults]: """Get a TTS evaluation run with results.""" run = get_tts_run_by_id( @@ -185,11 +189,18 @@ def get_tts_evaluation_run( results_total = 0 if include_results: + storage = None + if include_signed_url: + storage = get_cloud_storage( + session=session, project_id=auth_context.project_.id + ) + results, results_total = get_results_by_run_id( session=session, run_id=run_id, org_id=auth_context.organization_.id, project_id=auth_context.project_.id, + storage=storage, ) return APIResponse.success_response( diff --git a/backend/app/api/routes/tts_evaluations/result.py b/backend/app/api/routes/tts_evaluations/result.py index 8e8e0ffbd..e0da77700 100644 --- a/backend/app/api/routes/tts_evaluations/result.py +++ b/backend/app/api/routes/tts_evaluations/result.py @@ -2,10 +2,11 @@ import logging -from fastapi import APIRouter, Body, Depends, HTTPException +from fastapi import APIRouter, Body, Depends, HTTPException, Query from app.api.deps import AuthContextDep, SessionDep from app.api.permissions import Permission, require_permission +from app.core.cloud import get_cloud_storage from app.crud.tts_evaluations import ( get_tts_result_by_id, update_tts_human_feedback, @@ -92,6 +93,9 @@ def get_result( session: SessionDep, auth_context: AuthContextDep, result_id: int, + include_signed_url: bool = Query( + False, description="Include signed URL for generated audio file" + ), ) -> APIResponse[TTSResultPublic]: """Get a TTS result by ID.""" result = get_tts_result_by_id( @@ -104,4 +108,13 @@ def get_result( if not result: raise HTTPException(status_code=404, detail="Result not found") - return APIResponse.success_response(data=TTSResultPublic.from_model(result)) + signed_url = None + if include_signed_url: + storage = get_cloud_storage( + session=session, project_id=auth_context.project_.id + ) + signed_url = storage.get_signed_url_or_none(result.object_store_url) + + return APIResponse.success_response( + data=TTSResultPublic.from_model(result, signed_url=signed_url) + ) diff --git a/backend/app/core/cloud/storage.py b/backend/app/core/cloud/storage.py index 727380726..1ca7e841d 100644 --- a/backend/app/core/cloud/storage.py +++ b/backend/app/core/cloud/storage.py @@ -135,6 +135,31 @@ def get_signed_url(self, url: str, expires_in: int = 3600) -> str: """Generate a signed URL with an optional expiry""" pass + def get_signed_url_or_none( + self, url: str | None, expires_in: int = 3600 + ) -> str | None: + """Generate a signed URL, returning None if url is empty or on failure. + + A safe wrapper around get_signed_url that never raises. + + Args: + url: Object store URL (e.g., s3://bucket/key). Returns None if falsy. + expires_in: Expiry time in seconds (default: 1 hour) + + Returns: + Signed URL string, or None on failure + """ + if not url: + return None + try: + return self.get_signed_url(url, expires_in) + except Exception: + logger.warning( + f"[get_signed_url_or_none] Failed to generate signed URL | " + f"project_id: {self.project_id}" + ) + return None + @abstractmethod def delete(self, url: str) -> None: """Delete a file from storage""" diff --git a/backend/app/crud/stt_evaluations/result.py b/backend/app/crud/stt_evaluations/result.py index b6536facf..b3c41d78d 100644 --- a/backend/app/crud/stt_evaluations/result.py +++ b/backend/app/crud/stt_evaluations/result.py @@ -103,14 +103,9 @@ def get_results_by_run_id( # Convert to response models results = [] for result, sample, file in rows: - signed_url = None - if storage: - try: - signed_url = storage.get_signed_url(file.object_store_url) - except Exception as e: - logger.warning( - f"[get_results_by_run_id] Failed to generate signed URL: {e}" - ) + signed_url = ( + storage.get_signed_url_or_none(file.object_store_url) if storage else None + ) sample_public = STTSamplePublic( id=sample.id, diff --git a/backend/app/crud/tts_evaluations/cron.py b/backend/app/crud/tts_evaluations/cron.py index 0b478b2dd..d14f76fc4 100644 --- a/backend/app/crud/tts_evaluations/cron.py +++ b/backend/app/crud/tts_evaluations/cron.py @@ -151,7 +151,9 @@ async def _on_batch_succeeded(batch_job: BatchJob, provider_name: str) -> bool: return True async def _on_already_succeeded(batch_job: BatchJob, provider_name: str) -> bool: - pending = get_pending_results_for_run(session, run.id, provider_name) + pending = get_pending_results_for_run( + session=session, run_id=run.id, provider=provider_name + ) if pending: logger.info( f"{log_prefix} Dispatching reprocessing for " diff --git a/backend/app/crud/tts_evaluations/result.py b/backend/app/crud/tts_evaluations/result.py index 9acc73fd6..68e10770d 100644 --- a/backend/app/crud/tts_evaluations/result.py +++ b/backend/app/crud/tts_evaluations/result.py @@ -5,6 +5,7 @@ from sqlmodel import Session, func, select +from app.core.cloud.storage import CloudStorage from app.core.exception_handlers import HTTPException from app.core.util import now from app.models.job import JobStatus @@ -104,6 +105,7 @@ def get_results_by_run_id( run_id: int, org_id: int, project_id: int, + storage: CloudStorage | None = None, ) -> tuple[list[TTSResultPublic], int]: """Get all results for an evaluation run. @@ -112,6 +114,7 @@ def get_results_by_run_id( run_id: Run ID org_id: Organization ID project_id: Project ID + storage: Optional cloud storage instance for generating signed URLs Returns: tuple[list[TTSResultPublic], int]: Results and total count @@ -127,7 +130,12 @@ def get_results_by_run_id( rows = session.exec(statement).all() total = len(rows) - results = [TTSResultPublic.from_model(result) for result in rows] + results = [] + for result in rows: + signed_url = ( + storage.get_signed_url_or_none(result.object_store_url) if storage else None + ) + results.append(TTSResultPublic.from_model(result, signed_url=signed_url)) return results, total diff --git a/backend/app/models/tts_evaluation.py b/backend/app/models/tts_evaluation.py index e67924f53..3ee796759 100644 --- a/backend/app/models/tts_evaluation.py +++ b/backend/app/models/tts_evaluation.py @@ -209,6 +209,7 @@ class TTSResultPublic(BaseModel): id: int sample_text: str object_store_url: str | None + signed_url: str | None = None duration_seconds: float | None = None size_bytes: int | None = None provider: str @@ -224,12 +225,18 @@ class TTSResultPublic(BaseModel): updated_at: datetime @classmethod - def from_model(cls, result: TTSResult) -> TTSResultPublic: + def from_model( + cls, + result: TTSResult, + *, + signed_url: str | None = None, + ) -> TTSResultPublic: """Create from a TTSResult model instance.""" return cls( id=result.id, sample_text=result.sample_text, object_store_url=result.object_store_url, + signed_url=signed_url, duration_seconds=(result.metadata_ or {}).get("duration_seconds"), size_bytes=(result.metadata_ or {}).get("size_bytes"), provider=result.provider, From b34e4bb3ca0db0c0555825edbe1d30f79917e9fe Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Thu, 12 Mar 2026 15:48:19 +0530 Subject: [PATCH 2/5] update testcases --- .../app/tests/api/routes/test_stt_evaluation.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/backend/app/tests/api/routes/test_stt_evaluation.py b/backend/app/tests/api/routes/test_stt_evaluation.py index c322bb7c0..7ef89be22 100644 --- a/backend/app/tests/api/routes/test_stt_evaluation.py +++ b/backend/app/tests/api/routes/test_stt_evaluation.py @@ -653,7 +653,7 @@ def test_get_stt_dataset_with_signed_url( """Test getting an STT dataset with signed URLs for audio files.""" # Mock cloud storage to return signed URLs mock_storage = MagicMock() - mock_storage.get_signed_url.return_value = ( + mock_storage.get_signed_url_or_none.return_value = ( "https://signed-url.example.com/audio.mp3" ) mock_get_cloud_storage.return_value = mock_storage @@ -691,7 +691,7 @@ def test_get_stt_dataset_with_signed_url( # Verify cloud storage was called mock_get_cloud_storage.assert_called_once() - mock_storage.get_signed_url.assert_called_once() + mock_storage.get_signed_url_or_none.assert_called_once() def test_get_stt_dataset_without_signed_url( self, @@ -741,9 +741,7 @@ def test_get_stt_dataset_signed_url_failure( """Test getting an STT dataset when signed URL generation fails.""" # Mock cloud storage to raise an exception mock_storage = MagicMock() - mock_storage.get_signed_url.side_effect = Exception( - "Failed to generate signed URL" - ) + mock_storage.get_signed_url_or_none.return_value = None mock_get_cloud_storage.return_value = mock_storage dataset = create_test_stt_dataset( @@ -953,7 +951,7 @@ def test_get_stt_run_with_signed_url( """Test getting an STT run with signed URLs for audio files in results.""" # Mock cloud storage to return signed URLs mock_storage = MagicMock() - mock_storage.get_signed_url.return_value = ( + mock_storage.get_signed_url_or_none.return_value = ( "https://signed-url.example.com/audio.mp3" ) mock_get_cloud_storage.return_value = mock_storage @@ -1010,7 +1008,7 @@ def test_get_stt_run_with_signed_url( # Verify cloud storage was called mock_get_cloud_storage.assert_called_once() - mock_storage.get_signed_url.assert_called_once() + mock_storage.get_signed_url_or_none.assert_called_once() def test_get_stt_run_without_signed_url( self, @@ -1076,9 +1074,7 @@ def test_get_stt_run_signed_url_failure( """Test getting an STT run when signed URL generation fails.""" # Mock cloud storage to raise an exception mock_storage = MagicMock() - mock_storage.get_signed_url.side_effect = Exception( - "Failed to generate signed URL" - ) + mock_storage.get_signed_url_or_none.return_value = None mock_get_cloud_storage.return_value = mock_storage # Create dataset, sample, run, and result From 4db26892ede35173012181e36c61c65d5d497b93 Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Thu, 12 Mar 2026 18:22:52 +0530 Subject: [PATCH 3/5] reverting unnecessary changes --- .../app/api/routes/stt_evaluations/dataset.py | 2 +- .../app/api/routes/tts_evaluations/result.py | 2 +- backend/app/core/cloud/storage.py | 25 ------------------- backend/app/crud/stt_evaluations/result.py | 4 +-- backend/app/crud/tts_evaluations/result.py | 2 +- .../tests/api/routes/test_stt_evaluation.py | 12 ++++----- 6 files changed, 10 insertions(+), 37 deletions(-) diff --git a/backend/app/api/routes/stt_evaluations/dataset.py b/backend/app/api/routes/stt_evaluations/dataset.py index 395518b9a..a253bc445 100644 --- a/backend/app/api/routes/stt_evaluations/dataset.py +++ b/backend/app/api/routes/stt_evaluations/dataset.py @@ -169,7 +169,7 @@ def get_dataset( for s in sample_records: signed_url = None if storage and s.file_id in file_map: - signed_url = storage.get_signed_url_or_none( + signed_url = storage.get_signed_url( file_map[s.file_id].object_store_url ) diff --git a/backend/app/api/routes/tts_evaluations/result.py b/backend/app/api/routes/tts_evaluations/result.py index e0da77700..8d0820bc0 100644 --- a/backend/app/api/routes/tts_evaluations/result.py +++ b/backend/app/api/routes/tts_evaluations/result.py @@ -113,7 +113,7 @@ def get_result( storage = get_cloud_storage( session=session, project_id=auth_context.project_.id ) - signed_url = storage.get_signed_url_or_none(result.object_store_url) + signed_url = storage.get_signed_url(result.object_store_url) return APIResponse.success_response( data=TTSResultPublic.from_model(result, signed_url=signed_url) diff --git a/backend/app/core/cloud/storage.py b/backend/app/core/cloud/storage.py index 1ca7e841d..727380726 100644 --- a/backend/app/core/cloud/storage.py +++ b/backend/app/core/cloud/storage.py @@ -135,31 +135,6 @@ def get_signed_url(self, url: str, expires_in: int = 3600) -> str: """Generate a signed URL with an optional expiry""" pass - def get_signed_url_or_none( - self, url: str | None, expires_in: int = 3600 - ) -> str | None: - """Generate a signed URL, returning None if url is empty or on failure. - - A safe wrapper around get_signed_url that never raises. - - Args: - url: Object store URL (e.g., s3://bucket/key). Returns None if falsy. - expires_in: Expiry time in seconds (default: 1 hour) - - Returns: - Signed URL string, or None on failure - """ - if not url: - return None - try: - return self.get_signed_url(url, expires_in) - except Exception: - logger.warning( - f"[get_signed_url_or_none] Failed to generate signed URL | " - f"project_id: {self.project_id}" - ) - return None - @abstractmethod def delete(self, url: str) -> None: """Delete a file from storage""" diff --git a/backend/app/crud/stt_evaluations/result.py b/backend/app/crud/stt_evaluations/result.py index b3c41d78d..4458086e6 100644 --- a/backend/app/crud/stt_evaluations/result.py +++ b/backend/app/crud/stt_evaluations/result.py @@ -103,9 +103,7 @@ def get_results_by_run_id( # Convert to response models results = [] for result, sample, file in rows: - signed_url = ( - storage.get_signed_url_or_none(file.object_store_url) if storage else None - ) + signed_url = storage.get_signed_url(file.object_store_url) if storage else None sample_public = STTSamplePublic( id=sample.id, diff --git a/backend/app/crud/tts_evaluations/result.py b/backend/app/crud/tts_evaluations/result.py index 68e10770d..628fba744 100644 --- a/backend/app/crud/tts_evaluations/result.py +++ b/backend/app/crud/tts_evaluations/result.py @@ -133,7 +133,7 @@ def get_results_by_run_id( results = [] for result in rows: signed_url = ( - storage.get_signed_url_or_none(result.object_store_url) if storage else None + storage.get_signed_url(result.object_store_url) if storage else None ) results.append(TTSResultPublic.from_model(result, signed_url=signed_url)) diff --git a/backend/app/tests/api/routes/test_stt_evaluation.py b/backend/app/tests/api/routes/test_stt_evaluation.py index 7ef89be22..926870d4e 100644 --- a/backend/app/tests/api/routes/test_stt_evaluation.py +++ b/backend/app/tests/api/routes/test_stt_evaluation.py @@ -653,7 +653,7 @@ def test_get_stt_dataset_with_signed_url( """Test getting an STT dataset with signed URLs for audio files.""" # Mock cloud storage to return signed URLs mock_storage = MagicMock() - mock_storage.get_signed_url_or_none.return_value = ( + mock_storage.get_signed_url.return_value = ( "https://signed-url.example.com/audio.mp3" ) mock_get_cloud_storage.return_value = mock_storage @@ -691,7 +691,7 @@ def test_get_stt_dataset_with_signed_url( # Verify cloud storage was called mock_get_cloud_storage.assert_called_once() - mock_storage.get_signed_url_or_none.assert_called_once() + mock_storage.get_signed_url.assert_called_once() def test_get_stt_dataset_without_signed_url( self, @@ -741,7 +741,7 @@ def test_get_stt_dataset_signed_url_failure( """Test getting an STT dataset when signed URL generation fails.""" # Mock cloud storage to raise an exception mock_storage = MagicMock() - mock_storage.get_signed_url_or_none.return_value = None + mock_storage.get_signed_url.return_value = None mock_get_cloud_storage.return_value = mock_storage dataset = create_test_stt_dataset( @@ -951,7 +951,7 @@ def test_get_stt_run_with_signed_url( """Test getting an STT run with signed URLs for audio files in results.""" # Mock cloud storage to return signed URLs mock_storage = MagicMock() - mock_storage.get_signed_url_or_none.return_value = ( + mock_storage.get_signed_url.return_value = ( "https://signed-url.example.com/audio.mp3" ) mock_get_cloud_storage.return_value = mock_storage @@ -1008,7 +1008,7 @@ def test_get_stt_run_with_signed_url( # Verify cloud storage was called mock_get_cloud_storage.assert_called_once() - mock_storage.get_signed_url_or_none.assert_called_once() + mock_storage.get_signed_url.assert_called_once() def test_get_stt_run_without_signed_url( self, @@ -1074,7 +1074,7 @@ def test_get_stt_run_signed_url_failure( """Test getting an STT run when signed URL generation fails.""" # Mock cloud storage to raise an exception mock_storage = MagicMock() - mock_storage.get_signed_url_or_none.return_value = None + mock_storage.get_signed_url.return_value = None mock_get_cloud_storage.return_value = mock_storage # Create dataset, sample, run, and result From 4928ce5bed24cb4fb5b4880f5dd5040ccef6d677 Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Thu, 12 Mar 2026 18:34:37 +0530 Subject: [PATCH 4/5] cleanups for PEP8 --- backend/app/api/routes/stt_evaluations/dataset.py | 2 +- backend/app/crud/stt_evaluations/result.py | 8 ++++---- backend/app/crud/tts_evaluations/cron.py | 4 +--- backend/app/crud/tts_evaluations/result.py | 2 +- .../app/tests/api/routes/test_stt_evaluation.py | 14 +++++++------- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/backend/app/api/routes/stt_evaluations/dataset.py b/backend/app/api/routes/stt_evaluations/dataset.py index a253bc445..ea6ee9362 100644 --- a/backend/app/api/routes/stt_evaluations/dataset.py +++ b/backend/app/api/routes/stt_evaluations/dataset.py @@ -10,9 +10,9 @@ from app.crud.file import get_files_by_ids from app.crud.language import get_language_by_id from app.crud.stt_evaluations import ( + get_samples_by_dataset_id, get_stt_dataset_by_id, list_stt_datasets, - get_samples_by_dataset_id, ) from app.models.stt_evaluation import ( STTDatasetCreate, diff --git a/backend/app/crud/stt_evaluations/result.py b/backend/app/crud/stt_evaluations/result.py index 4458086e6..0e681f5dc 100644 --- a/backend/app/crud/stt_evaluations/result.py +++ b/backend/app/crud/stt_evaluations/result.py @@ -2,17 +2,17 @@ import logging -from sqlmodel import Session, select, func +from sqlmodel import Session, func, select +from app.core.cloud.storage import CloudStorage from app.core.exception_handlers import HTTPException from app.core.util import now from app.models.file import File -from app.core.cloud.storage import CloudStorage from app.models.stt_evaluation import ( STTResult, + STTResultWithSample, STTSample, STTSamplePublic, - STTResultWithSample, ) logger = logging.getLogger(__name__) @@ -219,4 +219,4 @@ def count_results_by_status( rows = session.exec(statement).all() - return {status: count for status, count in rows} + return dict(rows) diff --git a/backend/app/crud/tts_evaluations/cron.py b/backend/app/crud/tts_evaluations/cron.py index d14f76fc4..62c6a4faa 100644 --- a/backend/app/crud/tts_evaluations/cron.py +++ b/backend/app/crud/tts_evaluations/cron.py @@ -13,8 +13,6 @@ from sqlmodel import Session -from app.models.batch_job import BatchJobType - from app.celery.utils import start_low_priority_job from app.core.batch import GeminiBatchProvider from app.crud.evaluations.cron_utils import ( @@ -29,7 +27,7 @@ ) from app.crud.tts_evaluations.run import update_tts_run from app.models import EvaluationRun -from app.models.batch_job import BatchJob +from app.models.batch_job import BatchJob, BatchJobType from app.models.job import JobStatus from app.models.stt_evaluation import EvaluationType diff --git a/backend/app/crud/tts_evaluations/result.py b/backend/app/crud/tts_evaluations/result.py index 628fba744..2095f7def 100644 --- a/backend/app/crud/tts_evaluations/result.py +++ b/backend/app/crud/tts_evaluations/result.py @@ -302,4 +302,4 @@ def count_results_by_status( rows = session.exec(statement).all() - return {status: count for status, count in rows} + return dict(rows) diff --git a/backend/app/tests/api/routes/test_stt_evaluation.py b/backend/app/tests/api/routes/test_stt_evaluation.py index 926870d4e..6f120277f 100644 --- a/backend/app/tests/api/routes/test_stt_evaluation.py +++ b/backend/app/tests/api/routes/test_stt_evaluation.py @@ -1,14 +1,14 @@ -import pytest from unittest.mock import MagicMock, patch +import pytest from fastapi.testclient import TestClient from sqlmodel import Session -from app.models import EvaluationDataset, EvaluationRun, File, FileType -from app.models.stt_evaluation import STTSample, STTResult, EvaluationType +from app.core.util import now from app.crud.language import get_language_by_locale +from app.models import EvaluationDataset, EvaluationRun, File, FileType +from app.models.stt_evaluation import EvaluationType, STTResult, STTSample from app.tests.utils.auth import TestAuthContext -from app.core.util import now # Helper functions @@ -1274,7 +1274,7 @@ def test_list_audio_files_with_signed_urls( mock_get_cloud_storage.return_value = mock_storage # Create test file - file = create_test_file( + _file = create_test_file( db=db, organization_id=user_api_key.organization_id, project_id=user_api_key.project_id, @@ -1310,7 +1310,7 @@ def test_list_audio_files_without_signed_urls( ) -> None: """Test listing audio files without signed URLs.""" # Create test file - file = create_test_file( + _file = create_test_file( db=db, organization_id=user_api_key.organization_id, project_id=user_api_key.project_id, @@ -1341,7 +1341,7 @@ def test_list_audio_files_project_isolation( ) -> None: """Test that audio files are isolated by project.""" # Create file in user's project - user_file = create_test_file( + _user_file = create_test_file( db=db, organization_id=user_api_key.organization_id, project_id=user_api_key.project_id, From 60714bc0792cb439b8a39fa8df54624bfe84ac65 Mon Sep 17 00:00:00 2001 From: AkhileshNegi Date: Thu, 12 Mar 2026 19:01:33 +0530 Subject: [PATCH 5/5] adding a guard --- backend/app/api/routes/tts_evaluations/result.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/api/routes/tts_evaluations/result.py b/backend/app/api/routes/tts_evaluations/result.py index 8d0820bc0..2f1998fd0 100644 --- a/backend/app/api/routes/tts_evaluations/result.py +++ b/backend/app/api/routes/tts_evaluations/result.py @@ -109,7 +109,7 @@ def get_result( raise HTTPException(status_code=404, detail="Result not found") signed_url = None - if include_signed_url: + if include_signed_url and result.object_store_url is not None: storage = get_cloud_storage( session=session, project_id=auth_context.project_.id )