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
24 changes: 23 additions & 1 deletion tests/errors_test.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from datetime import datetime
from unittest.mock import Mock, AsyncMock

import pytest

from traveltimepy import Client, AsyncClient
from traveltimepy.errors import TravelTimeApiError
from traveltimepy.errors import TravelTimeApiError, TravelTimeError
from traveltimepy.requests.common import Coordinates
from traveltimepy.requests.time_map import TimeMapDepartureSearch
from traveltimepy.requests.transportation import Driving
Expand Down Expand Up @@ -65,3 +66,24 @@ def test_invalid_request_sync(client: Client):
intersections=[],
)
assert e.value.status_code == 422


def test_unexpected_error_response_sync():
mock_response = Mock()
mock_response.status_code = 400
mock_response.json.return_value = {"unexpected": "format"}

with Client("test", "test") as client:
with pytest.raises(TravelTimeError, match="unexpected response"):
client._handle_response(mock_response, Mock)


@pytest.mark.asyncio
async def test_unexpected_error_response_async():
mock_response = AsyncMock()
mock_response.status = 400
mock_response.text.return_value = '{"unexpected": "format"}'

async with AsyncClient("test", "test") as client:
with pytest.raises(TravelTimeError, match="unexpected response"):
await client._handle_response(mock_response, Mock)
11 changes: 9 additions & 2 deletions traveltimepy/async_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import aiohttp
from aiohttp import ClientSession, ClientResponse, BasicAuth, TCPConnector
from aiolimiter import AsyncLimiter
from pydantic import BaseModel
from pydantic import BaseModel, ValidationError
from tenacity import (
retry,
stop_after_attempt,
Expand All @@ -25,6 +25,7 @@
from traveltimepy.accept_type import AcceptType
from traveltimepy.base_client import BaseClient, __version__
from traveltimepy.errors import (
TravelTimeError,
TravelTimeJsonError,
TravelTimeServerError,
)
Expand Down Expand Up @@ -265,7 +266,13 @@ async def _handle_response(
text = await response.text()
json_data = json.loads(text)
if response.status != 200:
error = ResponseError.model_validate_json(json.dumps(json_data))
try:
error = ResponseError.model_validate_json(json.dumps(json_data))
except ValidationError:
raise TravelTimeError(
f"Server returned status code {response.status} "
f"with unexpected response: {json_data}"
)
if response.status >= 500:
raise TravelTimeServerError(error.description)
else:
Expand Down
11 changes: 9 additions & 2 deletions traveltimepy/sync_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Optional, Dict, TypeVar, Type, List, cast

import requests
from pydantic import BaseModel
from pydantic import BaseModel, ValidationError
from requests.adapters import HTTPAdapter
from requests.auth import HTTPBasicAuth
from requests_ratelimiter import LimiterSession
Expand All @@ -26,6 +26,7 @@
from traveltimepy.accept_type import AcceptType
from traveltimepy.base_client import BaseClient, __version__
from traveltimepy.errors import (
TravelTimeError,
TravelTimeJsonError,
TravelTimeServerError,
)
Expand Down Expand Up @@ -316,7 +317,13 @@ def _handle_response(
json_data = {"error": "Invalid JSON response"}

if response.status_code != 200:
error = ResponseError.model_validate_json(json.dumps(json_data))
try:
error = ResponseError.model_validate_json(json.dumps(json_data))
except ValidationError:
raise TravelTimeError(
f"Server returned status code {response.status_code} "
f"with unexpected response: {json_data}"
)
if response.status_code >= 500:
raise TravelTimeServerError(error.description)
else:
Expand Down
Loading