Skip to content

Commit 8fb9523

Browse files
committed
feat(python/sdk): Add info about HTTP response status code (#7653)
GitOrigin-RevId: c6fc606f037f04da42872e72797fe66ca441b19e
1 parent 22690b5 commit 8fb9523

File tree

7 files changed

+249
-70
lines changed

7 files changed

+249
-70
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,32 @@ The asynchronous approach allows the application to continue running while the t
937937

938938
You can identify those two approaches by the `_async` suffix in the `Transcriber`'s method name (e.g. `transcribe` vs `transcribe_async`).
939939

940+
## Getting the HTTP status code
941+
942+
There are two ways of accessing the HTTP status code:
943+
944+
- All custom AssemblyAI Error classes have a `status_code` attribute.
945+
- The latest HTTP response is stored in `aai.Client.get_default().latest_response` after every API call. This approach works also if no Exception is thrown.
946+
947+
```python
948+
transcriber = aai.Transcriber()
949+
950+
# Option 1: Catch the error
951+
try:
952+
transcript = transcriber.submit("./example.mp3")
953+
except aai.AssemblyAIError as e:
954+
print(e.status_code)
955+
956+
# Option 2: Access the latest response through the client
957+
client = aai.Client.get_default()
958+
959+
try:
960+
transcript = transcriber.submit("./example.mp3")
961+
except:
962+
print(client.last_response)
963+
print(client.last_response.status_code)
964+
```
965+
940966
## Polling Intervals
941967

942968
By default we poll the `Transcript`'s status each `3s`. In case you would like to adjust that interval:

assemblyai/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.35.1"
1+
__version__ = "0.36.0"

assemblyai/api.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ def create_transcript(
4343
)
4444
if response.status_code != httpx.codes.OK:
4545
raise types.TranscriptError(
46-
f"failed to transcribe url {request.audio_url}: {_get_error_message(response)}"
46+
f"failed to transcribe url {request.audio_url}: {_get_error_message(response)}",
47+
response.status_code,
4748
)
4849

4950
return types.TranscriptResponse.parse_obj(response.json())
@@ -60,6 +61,7 @@ def get_transcript(
6061
if response.status_code != httpx.codes.OK:
6162
raise types.TranscriptError(
6263
f"failed to retrieve transcript {transcript_id}: {_get_error_message(response)}",
64+
response.status_code,
6365
)
6466

6567
return types.TranscriptResponse.parse_obj(response.json())
@@ -76,6 +78,7 @@ def delete_transcript(
7678
if response.status_code != httpx.codes.OK:
7779
raise types.TranscriptError(
7880
f"failed to delete transcript {transcript_id}: {_get_error_message(response)}",
81+
response.status_code,
7982
)
8083

8184
return types.TranscriptResponse.parse_obj(response.json())
@@ -102,7 +105,8 @@ def upload_file(
102105

103106
if response.status_code != httpx.codes.OK:
104107
raise types.TranscriptError(
105-
f"Failed to upload audio file: {_get_error_message(response)}"
108+
f"Failed to upload audio file: {_get_error_message(response)}",
109+
response.status_code,
106110
)
107111

108112
return response.json()["upload_url"]
@@ -127,7 +131,8 @@ def export_subtitles_srt(
127131

128132
if response.status_code != httpx.codes.OK:
129133
raise types.TranscriptError(
130-
f"failed to export SRT for transcript {transcript_id}: {_get_error_message(response)}"
134+
f"failed to export SRT for transcript {transcript_id}: {_get_error_message(response)}",
135+
response.status_code,
131136
)
132137

133138
return response.text
@@ -152,7 +157,8 @@ def export_subtitles_vtt(
152157

153158
if response.status_code != httpx.codes.OK:
154159
raise types.TranscriptError(
155-
f"failed to export VTT for transcript {transcript_id}: {_get_error_message(response)}"
160+
f"failed to export VTT for transcript {transcript_id}: {_get_error_message(response)}",
161+
response.status_code,
156162
)
157163

158164
return response.text
@@ -174,7 +180,8 @@ def word_search(
174180

175181
if response.status_code != httpx.codes.OK:
176182
raise types.TranscriptError(
177-
f"failed to search words in transcript {transcript_id}: {_get_error_message(response)}"
183+
f"failed to search words in transcript {transcript_id}: {_get_error_message(response)}",
184+
response.status_code,
178185
)
179186

180187
return types.WordSearchMatchResponse.parse_obj(response.json())
@@ -199,17 +206,20 @@ def get_redacted_audio(
199206

200207
if response.status_code == httpx.codes.ACCEPTED:
201208
raise types.RedactedAudioIncompleteError(
202-
f"redacted audio for transcript {transcript_id} is not ready yet"
209+
f"redacted audio for transcript {transcript_id} is not ready yet",
210+
response.status_code,
203211
)
204212

205213
if response.status_code == httpx.codes.BAD_REQUEST:
206214
raise types.RedactedAudioExpiredError(
207-
f"redacted audio for transcript {transcript_id} is no longer available"
215+
f"redacted audio for transcript {transcript_id} is no longer available",
216+
response.status_code,
208217
)
209218

210219
if response.status_code != httpx.codes.OK:
211220
raise types.TranscriptError(
212-
f"failed to retrieve redacted audio for transcript {transcript_id}: {_get_error_message(response)}"
221+
f"failed to retrieve redacted audio for transcript {transcript_id}: {_get_error_message(response)}",
222+
response.status_code,
213223
)
214224

215225
return types.RedactedAudioResponse.parse_obj(response.json())
@@ -225,7 +235,8 @@ def get_sentences(
225235

226236
if response.status_code != httpx.codes.OK:
227237
raise types.TranscriptError(
228-
f"failed to retrieve sentences for transcript {transcript_id}: {_get_error_message(response)}"
238+
f"failed to retrieve sentences for transcript {transcript_id}: {_get_error_message(response)}",
239+
response.status_code,
229240
)
230241

231242
return types.SentencesResponse.parse_obj(response.json())
@@ -241,7 +252,8 @@ def get_paragraphs(
241252

242253
if response.status_code != httpx.codes.OK:
243254
raise types.TranscriptError(
244-
f"failed to retrieve paragraphs for transcript {transcript_id}: {_get_error_message(response)}"
255+
f"failed to retrieve paragraphs for transcript {transcript_id}: {_get_error_message(response)}",
256+
response.status_code,
245257
)
246258

247259
return types.ParagraphsResponse.parse_obj(response.json())
@@ -264,7 +276,8 @@ def list_transcripts(
264276

265277
if response.status_code != httpx.codes.OK:
266278
raise types.AssemblyAIError(
267-
f"failed to retrieve transcripts: {_get_error_message(response)}"
279+
f"failed to retrieve transcripts: {_get_error_message(response)}",
280+
response.status_code,
268281
)
269282

270283
return types.ListTranscriptResponse.parse_obj(response.json())
@@ -285,7 +298,8 @@ def lemur_question(
285298

286299
if response.status_code != httpx.codes.OK:
287300
raise types.LemurError(
288-
f"failed to call Lemur questions: {_get_error_message(response)}"
301+
f"failed to call Lemur questions: {_get_error_message(response)}",
302+
response.status_code,
289303
)
290304

291305
return types.LemurQuestionResponse.parse_obj(response.json())
@@ -306,7 +320,8 @@ def lemur_summarize(
306320

307321
if response.status_code != httpx.codes.OK:
308322
raise types.LemurError(
309-
f"failed to call Lemur summary: {_get_error_message(response)}"
323+
f"failed to call Lemur summary: {_get_error_message(response)}",
324+
response.status_code,
310325
)
311326

312327
return types.LemurSummaryResponse.parse_obj(response.json())
@@ -327,7 +342,8 @@ def lemur_action_items(
327342

328343
if response.status_code != httpx.codes.OK:
329344
raise types.LemurError(
330-
f"failed to call Lemur action items: {_get_error_message(response)}"
345+
f"failed to call Lemur action items: {_get_error_message(response)}",
346+
response.status_code,
331347
)
332348

333349
return types.LemurActionItemsResponse.parse_obj(response.json())
@@ -348,7 +364,8 @@ def lemur_task(
348364

349365
if response.status_code != httpx.codes.OK:
350366
raise types.LemurError(
351-
f"failed to call Lemur task: {_get_error_message(response)}"
367+
f"failed to call Lemur task: {_get_error_message(response)}",
368+
response.status_code,
352369
)
353370

354371
return types.LemurTaskResponse.parse_obj(response.json())
@@ -366,7 +383,8 @@ def lemur_purge_request_data(
366383

367384
if response.status_code != httpx.codes.OK:
368385
raise types.LemurError(
369-
f"Failed to purge LeMUR request data for provided request ID: {request.request_id}. Error: {_get_error_message(response)}"
386+
f"Failed to purge LeMUR request data for provided request ID: {request.request_id}. Error: {_get_error_message(response)}",
387+
response.status_code,
370388
)
371389

372390
return types.LemurPurgeResponse.parse_obj(response.json())
@@ -387,7 +405,8 @@ def lemur_get_response_data(
387405

388406
if response.status_code != httpx.codes.OK:
389407
raise types.LemurError(
390-
f"Failed to get LeMUR response data for provided request ID: {request_id}. Error: {_get_error_message(response)}"
408+
f"Failed to get LeMUR response data for provided request ID: {request_id}. Error: {_get_error_message(response)}",
409+
response.status_code,
391410
)
392411

393412
json_data = response.json()
@@ -411,7 +430,8 @@ def create_temporary_token(
411430

412431
if response.status_code != httpx.codes.OK:
413432
raise types.AssemblyAIError(
414-
f"Failed to create temporary token: {_get_error_message(response)}"
433+
f"Failed to create temporary token: {_get_error_message(response)}",
434+
response.status_code,
415435
)
416436

417437
data = types.RealtimeCreateTemporaryTokenResponse.parse_obj(response.json())

assemblyai/client.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import ClassVar, Optional
44

55
import httpx
6-
from typing_extensions import Self
76

87
from . import types
98
from .__version__ import __version__
@@ -41,14 +40,30 @@ def __init__(
4140

4241
headers = {"user-agent": user_agent}
4342
if self._settings.api_key:
44-
headers["authorization"] = self.settings.api_key
43+
headers["authorization"] = self._settings.api_key
44+
45+
self._last_response: Optional[httpx.Response] = None
46+
47+
def _store_response(response):
48+
self._last_response = response
4549

4650
self._http_client = httpx.Client(
4751
base_url=self.settings.base_url,
4852
headers=headers,
4953
timeout=self.settings.http_timeout,
54+
event_hooks={"response": [_store_response]},
5055
)
5156

57+
@property
58+
def last_response(self) -> Optional[httpx.Response]:
59+
"""
60+
Get the last HTTP response, corresponding to the last request sent from this client.
61+
62+
Returns:
63+
The last HTTP response.
64+
"""
65+
return self._last_response
66+
5267
@property
5368
def settings(self) -> types.Settings:
5469
"""
@@ -72,7 +87,7 @@ def http_client(self) -> httpx.Client:
7287
return self._http_client
7388

7489
@classmethod
75-
def get_default(cls, api_key_required: bool = True) -> Self:
90+
def get_default(cls, api_key_required: bool = True):
7691
"""
7792
Return the default client.
7893

0 commit comments

Comments
 (0)