Skip to content
Open
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
3 changes: 2 additions & 1 deletion speech_recognition/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
from urllib.request import Request, urlopen

from .audio import AudioData, get_flac_converter
from .exceptions import (
from .exceptions import ( # noqa: F401
RateLimitError,
RequestError,
TranscriptionFailed,
TranscriptionNotReady,
Expand Down
8 changes: 8 additions & 0 deletions speech_recognition/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ class TranscriptionNotReady(Exception):

class TranscriptionFailed(Exception):
pass


class RateLimitError(RequestError):
"""Raised when the speech recognition service returns an HTTP 429
(Too Many Requests) response, indicating the caller has been rate
limited.
"""
pass
6 changes: 5 additions & 1 deletion speech_recognition/recognizers/google.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing_extensions import NotRequired

from speech_recognition.audio import AudioData
from speech_recognition.exceptions import RequestError, UnknownValueError
from speech_recognition.exceptions import RateLimitError, RequestError, UnknownValueError


class Alternative(TypedDict):
Expand Down Expand Up @@ -215,6 +215,10 @@ def obtain_transcription(request: Request, timeout: int) -> str:
try:
response = urlopen(request, timeout=timeout)
except HTTPError as e:
if e.code == 429:
raise RateLimitError(
"recognition request failed: rate limited (HTTP 429): {}".format(e.reason),
)
raise RequestError("recognition request failed: {}".format(e.reason))
except URLError as e:
raise RequestError(
Expand Down
18 changes: 17 additions & 1 deletion tests/recognizers/test_google.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from unittest import TestCase
from unittest.mock import MagicMock, patch
from urllib.error import HTTPError
from urllib.request import Request

from speech_recognition import Recognizer
from speech_recognition.audio import AudioData
from speech_recognition.exceptions import RateLimitError
from speech_recognition.recognizers import google

MODULE_UNDER_TEST = "speech_recognition.recognizers.google"


Expand Down Expand Up @@ -114,6 +115,21 @@ def test_obtain(self, urlopen):
response.read.assert_called_once_with()
response.read.return_value.decode.assert_called_once_with("utf-8")

@patch(f"{MODULE_UNDER_TEST}.urlopen")
def test_obtain_rate_limited(self, urlopen):
request = MagicMock(spec=Request)
error = HTTPError(
url="http://example.com",
code=429,
msg="Too Many Requests",
hdrs={},
fp=None,
)
urlopen.side_effect = error

with self.assertRaises(RateLimitError):
google.obtain_transcription(request, 0)


@patch(f"{MODULE_UNDER_TEST}.OutputParser")
@patch(f"{MODULE_UNDER_TEST}.obtain_transcription")
Expand Down