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
2 changes: 1 addition & 1 deletion linkup/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.5"
__version__ = "0.2.6"
26 changes: 21 additions & 5 deletions linkup/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
LinkupInsufficientCreditError,
LinkupInvalidRequestError,
LinkupNoResultError,
LinkupTooManyRequestsError,
LinkupUnknownError,
)
from linkup.types import LinkupSearchResults, LinkupSourcedAnswer
Expand Down Expand Up @@ -268,11 +269,26 @@ def _raise_linkup_error(self, response: httpx.Response) -> None:
f"Original error message: {error_msg}."
)
elif response.status_code == 429:
raise LinkupInsufficientCreditError(
"The Linkup API returned an insufficient credit error (429). Make sure "
"you haven't exhausted your credits.\n"
f"Original error message: {error_msg}."
)
if code == "INSUFFICIENT_FUNDS_CREDITS":
raise LinkupInsufficientCreditError(
"The Linkup API returned an insufficient credit error (429). Make sure "
"you haven't exhausted your credits.\n"
f"Original error message: {error_msg}."
)
elif code == "TOO_MANY_REQUESTS":
raise LinkupTooManyRequestsError(
"The Linkup API returned a too many requests error (429). Make sure "
"you not sending too many requests at a time.\n"
f"Original error message: {error_msg}."
)
Comment thread
cjumel marked this conversation as resolved.
else:
raise LinkupUnknownError(
"The Linkup API returned an invalid request error (429). Make sure the "
"parameters you used are valid (correct values, types, mandatory "
"parameters, etc.) and you are using the latest version of the Python "
"SDK.\n"
f"Original error message: {error_msg}."
)
else:
raise LinkupUnknownError(
f"The Linkup API returned an unknown error ({response.status_code}).\n"
Expand Down
9 changes: 9 additions & 0 deletions linkup/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ class LinkupInsufficientCreditError(Exception):
pass


class LinkupTooManyRequestsError(Exception):
"""Too many requests error, raised when the Linkup API returns a 429 status code.

It is returned when you are sending too many requests at a time.
"""

pass


class LinkupUnknownError(Exception):
"""Unknown error, raised when the Linkup API returns an unknown status code."""

Expand Down
98 changes: 95 additions & 3 deletions tests/unit_tests/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
LinkupSourcedAnswer,
LinkupUnknownError,
)
from linkup.errors import LinkupInsufficientCreditError, LinkupNoResultError
from linkup.errors import (
LinkupInsufficientCreditError,
LinkupNoResultError,
LinkupTooManyRequestsError,
)
from linkup.types import LinkupSearchImageResult, LinkupSearchTextResult


Expand Down Expand Up @@ -221,7 +225,7 @@ def test_search_insufficient_credit_error(mocker: MockerFixture, client: LinkupC
mock_response.json.return_value = {
"statusCode": 429,
"error": {
"code": "INSUFFICIENT_CREDITS",
"code": "INSUFFICIENT_FUNDS_CREDITS",
"message": "You do not have enough credits to perform this request.",
"details": [],
},
Expand All @@ -236,6 +240,48 @@ def test_search_insufficient_credit_error(mocker: MockerFixture, client: LinkupC
client.search(query="foo", depth="standard", output_type="searchResults")


def test_search_too_many_requests_error(mocker: MockerFixture, client: LinkupClient) -> None:
mock_response = mocker.Mock()
mock_response.status_code = 429
mock_response.json.return_value = {
"statusCode": 429,
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "Too many requests.",
"details": [],
},
}

mocker.patch(
"linkup.client.LinkupClient._request",
return_value=mock_response,
)

with pytest.raises(LinkupTooManyRequestsError):
client.search(query="foo", depth="standard", output_type="searchResults")


def test_search_error_429_unknown_code(mocker: MockerFixture, client: LinkupClient) -> None:
mock_response = mocker.Mock()
mock_response.status_code = 429
mock_response.json.return_value = {
"statusCode": 429,
"error": {
"code": "FOOBAR",
"message": "Foobar",
"details": [],
},
}

mocker.patch(
"linkup.client.LinkupClient._request",
return_value=mock_response,
)

with pytest.raises(LinkupUnknownError):
client.search(query="foo", depth="standard", output_type="searchResults")


def test_search_structured_search_invalid_request(
mocker: MockerFixture,
client: LinkupClient,
Expand Down Expand Up @@ -543,7 +589,7 @@ async def test_async_search_insufficient_credit_error(
mock_response.json.return_value = {
"statusCode": 429,
"error": {
"code": "INSUFFICIENT_CREDITS",
"code": "INSUFFICIENT_FUNDS_CREDITS",
"message": "You do not have enough credits to perform this request.",
"details": [],
},
Expand All @@ -557,6 +603,52 @@ async def test_async_search_insufficient_credit_error(
await client.async_search(query="foo", depth="standard", output_type="searchResults")


@pytest.mark.asyncio
async def test_async_search_too_many_requests_error(
mocker: MockerFixture, client: LinkupClient
) -> None:
mock_response = mocker.Mock()
mock_response.status_code = 429
mock_response.json.return_value = {
"statusCode": 429,
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "Too many requests.",
"details": [],
},
}

mocker.patch(
"linkup.client.LinkupClient._async_request",
return_value=mock_response,
)
with pytest.raises(LinkupTooManyRequestsError):
await client.async_search(query="foo", depth="standard", output_type="searchResults")


@pytest.mark.asyncio
async def test_async_search_error_429_unknown_code(
mocker: MockerFixture, client: LinkupClient
) -> None:
mock_response = mocker.Mock()
mock_response.status_code = 429
mock_response.json.return_value = {
"statusCode": 429,
"error": {
"code": "FOOBAR",
"message": "Foobar",
"details": [],
},
}

mocker.patch(
"linkup.client.LinkupClient._async_request",
return_value=mock_response,
)
with pytest.raises(LinkupUnknownError):
await client.async_search(query="foo", depth="standard", output_type="searchResults")


@pytest.mark.asyncio
async def test_async_search_structured_search_invalid_request(
mocker: MockerFixture,
Expand Down