Skip to content

Commit 701a93f

Browse files
Add custom error for 429 too many requests (#26)
* Add custom error for 429 too many requests * Add unknown error on unknown 429
1 parent 706e59b commit 701a93f

File tree

4 files changed

+126
-9
lines changed

4 files changed

+126
-9
lines changed

linkup/_version.py

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

linkup/client.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
LinkupInsufficientCreditError,
1313
LinkupInvalidRequestError,
1414
LinkupNoResultError,
15+
LinkupTooManyRequestsError,
1516
LinkupUnknownError,
1617
)
1718
from linkup.types import LinkupSearchResults, LinkupSourcedAnswer
@@ -268,11 +269,26 @@ def _raise_linkup_error(self, response: httpx.Response) -> None:
268269
f"Original error message: {error_msg}."
269270
)
270271
elif response.status_code == 429:
271-
raise LinkupInsufficientCreditError(
272-
"The Linkup API returned an insufficient credit error (429). Make sure "
273-
"you haven't exhausted your credits.\n"
274-
f"Original error message: {error_msg}."
275-
)
272+
if code == "INSUFFICIENT_FUNDS_CREDITS":
273+
raise LinkupInsufficientCreditError(
274+
"The Linkup API returned an insufficient credit error (429). Make sure "
275+
"you haven't exhausted your credits.\n"
276+
f"Original error message: {error_msg}."
277+
)
278+
elif code == "TOO_MANY_REQUESTS":
279+
raise LinkupTooManyRequestsError(
280+
"The Linkup API returned a too many requests error (429). Make sure "
281+
"you not sending too many requests at a time.\n"
282+
f"Original error message: {error_msg}."
283+
)
284+
else:
285+
raise LinkupUnknownError(
286+
"The Linkup API returned an invalid request error (429). Make sure the "
287+
"parameters you used are valid (correct values, types, mandatory "
288+
"parameters, etc.) and you are using the latest version of the Python "
289+
"SDK.\n"
290+
f"Original error message: {error_msg}."
291+
)
276292
else:
277293
raise LinkupUnknownError(
278294
f"The Linkup API returned an unknown error ({response.status_code}).\n"

linkup/errors.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ class LinkupInsufficientCreditError(Exception):
3535
pass
3636

3737

38+
class LinkupTooManyRequestsError(Exception):
39+
"""Too many requests error, raised when the Linkup API returns a 429 status code.
40+
41+
It is returned when you are sending too many requests at a time.
42+
"""
43+
44+
pass
45+
46+
3847
class LinkupUnknownError(Exception):
3948
"""Unknown error, raised when the Linkup API returns an unknown status code."""
4049

tests/unit_tests/client_test.py

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
LinkupSourcedAnswer,
1616
LinkupUnknownError,
1717
)
18-
from linkup.errors import LinkupInsufficientCreditError, LinkupNoResultError
18+
from linkup.errors import (
19+
LinkupInsufficientCreditError,
20+
LinkupNoResultError,
21+
LinkupTooManyRequestsError,
22+
)
1923
from linkup.types import LinkupSearchImageResult, LinkupSearchTextResult
2024

2125

@@ -221,7 +225,7 @@ def test_search_insufficient_credit_error(mocker: MockerFixture, client: LinkupC
221225
mock_response.json.return_value = {
222226
"statusCode": 429,
223227
"error": {
224-
"code": "INSUFFICIENT_CREDITS",
228+
"code": "INSUFFICIENT_FUNDS_CREDITS",
225229
"message": "You do not have enough credits to perform this request.",
226230
"details": [],
227231
},
@@ -236,6 +240,48 @@ def test_search_insufficient_credit_error(mocker: MockerFixture, client: LinkupC
236240
client.search(query="foo", depth="standard", output_type="searchResults")
237241

238242

243+
def test_search_too_many_requests_error(mocker: MockerFixture, client: LinkupClient) -> None:
244+
mock_response = mocker.Mock()
245+
mock_response.status_code = 429
246+
mock_response.json.return_value = {
247+
"statusCode": 429,
248+
"error": {
249+
"code": "TOO_MANY_REQUESTS",
250+
"message": "Too many requests.",
251+
"details": [],
252+
},
253+
}
254+
255+
mocker.patch(
256+
"linkup.client.LinkupClient._request",
257+
return_value=mock_response,
258+
)
259+
260+
with pytest.raises(LinkupTooManyRequestsError):
261+
client.search(query="foo", depth="standard", output_type="searchResults")
262+
263+
264+
def test_search_error_429_unknown_code(mocker: MockerFixture, client: LinkupClient) -> None:
265+
mock_response = mocker.Mock()
266+
mock_response.status_code = 429
267+
mock_response.json.return_value = {
268+
"statusCode": 429,
269+
"error": {
270+
"code": "FOOBAR",
271+
"message": "Foobar",
272+
"details": [],
273+
},
274+
}
275+
276+
mocker.patch(
277+
"linkup.client.LinkupClient._request",
278+
return_value=mock_response,
279+
)
280+
281+
with pytest.raises(LinkupUnknownError):
282+
client.search(query="foo", depth="standard", output_type="searchResults")
283+
284+
239285
def test_search_structured_search_invalid_request(
240286
mocker: MockerFixture,
241287
client: LinkupClient,
@@ -543,7 +589,7 @@ async def test_async_search_insufficient_credit_error(
543589
mock_response.json.return_value = {
544590
"statusCode": 429,
545591
"error": {
546-
"code": "INSUFFICIENT_CREDITS",
592+
"code": "INSUFFICIENT_FUNDS_CREDITS",
547593
"message": "You do not have enough credits to perform this request.",
548594
"details": [],
549595
},
@@ -557,6 +603,52 @@ async def test_async_search_insufficient_credit_error(
557603
await client.async_search(query="foo", depth="standard", output_type="searchResults")
558604

559605

606+
@pytest.mark.asyncio
607+
async def test_async_search_too_many_requests_error(
608+
mocker: MockerFixture, client: LinkupClient
609+
) -> None:
610+
mock_response = mocker.Mock()
611+
mock_response.status_code = 429
612+
mock_response.json.return_value = {
613+
"statusCode": 429,
614+
"error": {
615+
"code": "TOO_MANY_REQUESTS",
616+
"message": "Too many requests.",
617+
"details": [],
618+
},
619+
}
620+
621+
mocker.patch(
622+
"linkup.client.LinkupClient._async_request",
623+
return_value=mock_response,
624+
)
625+
with pytest.raises(LinkupTooManyRequestsError):
626+
await client.async_search(query="foo", depth="standard", output_type="searchResults")
627+
628+
629+
@pytest.mark.asyncio
630+
async def test_async_search_error_429_unknown_code(
631+
mocker: MockerFixture, client: LinkupClient
632+
) -> None:
633+
mock_response = mocker.Mock()
634+
mock_response.status_code = 429
635+
mock_response.json.return_value = {
636+
"statusCode": 429,
637+
"error": {
638+
"code": "FOOBAR",
639+
"message": "Foobar",
640+
"details": [],
641+
},
642+
}
643+
644+
mocker.patch(
645+
"linkup.client.LinkupClient._async_request",
646+
return_value=mock_response,
647+
)
648+
with pytest.raises(LinkupUnknownError):
649+
await client.async_search(query="foo", depth="standard", output_type="searchResults")
650+
651+
560652
@pytest.mark.asyncio
561653
async def test_async_search_structured_search_invalid_request(
562654
mocker: MockerFixture,

0 commit comments

Comments
 (0)