Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions readalongs/web_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

from fastapi import Body, FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.responses import FileResponse, JSONResponse
from lxml import etree
from pydantic import BaseModel, Field
from starlette.background import BackgroundTask
Expand Down Expand Up @@ -272,16 +272,20 @@ async def assemble(
if not valid:
if non_convertible_words:
logs = (
"These words could not be converted from text to phonemes by g2p: '"
+ "', '".join(non_convertible_words)
+ "'."
"These words could not be converted from text to phonemes by g2p: ' "
+ " ', ' ".join(non_convertible_words)
+ " '."
)
else:
logs = "Logs: " + captured_logs.getvalue()
raise HTTPException(
return JSONResponse(
Copy link
Collaborator

@sergeleger sergeleger Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you prefer the explicitness of HTTPException it should work also, since HTTPException.detail accepts any type:

raise HTTPException(status_code=422, detail={                     
    "detail": "g2p could not be performed, please check your text or your language code. " + logs,
     "g2p_error_words": non_convertible_words,
     "partial_ras": xml_to_string(g2ped),
})

But introduces a breaking change for Studio-Web, since the detail key with the error message is one level deeper in the response:

const resp = await fetch(...);
if(resp.status_code===422) {
   const exception = await resp.json();
   const contentLog = exception["detail"]["detail"];
   const g2pBadWords = exception["detail"]["g2p_error_words"];
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It's good to know for future similar cases, but backwards compatibility is important here to allow updating the back end and the front end each on their own schedule, so I'll keep the JSONResponse with a status code.

status_code=422,
detail="g2p could not be performed, please check your text or your language code. "
+ logs,
content={
"detail": "g2p could not be performed, please check your text or your language code. "
+ logs,
"g2p_error_words": non_convertible_words,
"partial_ras": xml_to_string(g2ped),
},
)
# create grammar
dict_data, text_input = create_grammar(g2ped)
Expand Down
6 changes: 5 additions & 1 deletion tests/test_web_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,14 @@ def test_empty_g2p(self):
with redirect_stderr(StringIO()):
response = self.API_CLIENT.post("/api/v1/assemble", json=request)
self.assertEqual(response.status_code, 422)
content_log = response.json()["detail"]
content = response.json()
content_log = content["detail"]
for message_part in ["These words could not", "24", "23"]:
self.assertIn(message_part, content_log)

self.assertEqual(content["g2p_error_words"], ["24", "23", "99", "1234"])
self.assertIn("partial_ras", content)

def test_langs(self):
# Test the langs endpoint
with redirect_stderr(StringIO()):
Expand Down