Skip to content

Commit

Permalink
refactor(api): update api version and improve error handling
Browse files Browse the repository at this point in the history
- Update API version to 3.5 in request headers
- Refactor error handling with dedicated _request_check_status method
- Simplify model classes by removing redundant post_init logic
- Update pages models and tests/fixtures to comply with new API version
  • Loading branch information
bendikrb committed Oct 24, 2024
1 parent 53c3e76 commit b2e4826
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 165 deletions.
37 changes: 23 additions & 14 deletions nrk_psapi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from http import HTTPStatus
import socket

from aiohttp.client import ClientError, ClientResponseError, ClientSession
from aiohttp.client import ClientError, ClientResponse, ClientResponseError, ClientSession
from aiohttp.hdrs import METH_GET
import async_timeout
import orjson
Expand All @@ -26,6 +26,9 @@
from .models.catalog import (
Episode,
Podcast,
PodcastSequential,
PodcastStandard,
PodcastUmbrella,
Program,
Season,
SeriesType,
Expand Down Expand Up @@ -56,7 +59,6 @@
from .utils import (
fetch_file_info,
get_nested_items,
sanitize_string,
tiled_images,
)

Expand Down Expand Up @@ -92,7 +94,7 @@ def __post_init__(self):
def request_header(self) -> dict[str, str]:
"""Generate a header for HTTP requests to the server."""
return {
"Accept": "application/json",
"Accept": "application/json;api-version=3.5",
"User-Agent": self.user_agent or f"NrkPodcastAPI/{__version__}",
}

Expand Down Expand Up @@ -136,6 +138,17 @@ async def _request_paged(
page = 1
return await self._request(uri, method, params={"pageSize": page_size, "page": page}, **kwargs)

@staticmethod
async def _request_check_status(response: ClientResponse):
if response.status == HTTPStatus.TOO_MANY_REQUESTS:
raise NrkPsApiRateLimitError("Too many requests to NRK API. Try again later.")
if response.status == HTTPStatus.NOT_FOUND:
raise NrkPsApiNotFoundError("Resource not found")
if response.status == HTTPStatus.BAD_REQUEST:
raise NrkPsApiError("Bad request syntax or unsupported method")
if response.status != HTTPStatus.OK:
raise NrkPsApiError(response)

async def _request(
self,
uri: str,
Expand Down Expand Up @@ -169,8 +182,8 @@ async def _request(
url,
**kwargs,
headers=headers,
raise_for_status=self._request_check_status,
)
response.raise_for_status()
except asyncio.TimeoutError as exception:
raise NrkPsApiConnectionTimeoutError(
"Timeout occurred while connecting to NRK API"
Expand All @@ -180,12 +193,6 @@ async def _request(
ClientResponseError,
socket.gaierror,
) as exception:
if hasattr(exception, "status") and exception.status == HTTPStatus.TOO_MANY_REQUESTS:
raise NrkPsApiRateLimitError("Too many requests to NRK API. Try again later.") from exception
if hasattr(exception, "status") and exception.status == HTTPStatus.NOT_FOUND:
raise NrkPsApiNotFoundError("Resource not found") from exception
if hasattr(exception, "status") and exception.status == HTTPStatus.BAD_REQUEST:
raise NrkPsApiError("Bad request syntax or unsupported method") from exception
msg = f"Error occurred while communicating with NRK API: {exception}"
raise NrkPsApiConnectionError(msg) from exception

Expand Down Expand Up @@ -370,7 +377,9 @@ async def get_program(self, program_id: str) -> Program:
return Program.from_dict(result)

@cache(ignore=(0,))
async def get_podcast(self, podcast_id: str) -> Podcast:
async def get_podcast(
self, podcast_id: str
) -> Podcast | PodcastStandard | PodcastUmbrella | PodcastSequential:
"""Get podcast.
Args:
Expand Down Expand Up @@ -582,7 +591,7 @@ async def radio_page(self, page_id: str, section_id: str | None = None) -> Page
return page

for section in page.sections:
if isinstance(section, IncludedSection) and section.included.section_id == section_id:
if isinstance(section, IncludedSection) and section.id == section_id:
return section.included
return None

Expand Down Expand Up @@ -611,7 +620,7 @@ async def curated_podcasts(self) -> Curated:
if len(podcasts) > 1:
sections.append(
CuratedSection(
id=sanitize_string(section.included.title),
id=section.id,
title=section.included.title,
podcasts=podcasts,
)
Expand All @@ -630,7 +639,7 @@ async def generate_tiled_images(
tile_size: int = 100,
columns: int = 3,
aspect_ratio: str | None = None,
) -> bytes:
) -> bytes: # pragma: no cover
"""Proxies call to :func:`.utils.tiled_images`, passing on :attr:`~.session`."""
return await tiled_images(image_urls, tile_size, columns, aspect_ratio, session=self.session)

Expand Down
Loading

0 comments on commit b2e4826

Please sign in to comment.