From ecd12ed1688a5cab3dd4bbb127a2ac4764a71bf2 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 4 Oct 2026 17:04:18 +0200 Subject: [PATCH 1/2] Handle empty TV first air dates --- src/python_overseerr/models.py | 14 ++++++++++++- tests/test_overseerr.py | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/python_overseerr/models.py b/src/python_overseerr/models.py index b62ae00..fa36f69 100644 --- a/src/python_overseerr/models.py +++ b/src/python_overseerr/models.py @@ -12,6 +12,13 @@ from mashumaro.types import Discriminator +def deserialize_optional_date(value: str | None) -> date | None: + """Deserialize an optional date, treating an empty string as None.""" + if value is None or value == "": + return None + return date.fromisoformat(value) + + @dataclass class RequestCount(DataClassORJSONMixin): """Request count model.""" @@ -118,7 +125,12 @@ class TV(Result): """TV result model.""" mediaType = ResultMediaType.TV # noqa: N815 # pylint: disable=invalid-name - first_air_date: date = field(metadata=field_options(alias="firstAirDate")) + first_air_date: date | None = field( + metadata=field_options( + alias="firstAirDate", + deserialize=deserialize_optional_date, + ) + ) name: str original_language: str = field(metadata=field_options(alias="originalLanguage")) original_name: str = field(metadata=field_options(alias="originalName")) diff --git a/tests/test_overseerr.py b/tests/test_overseerr.py index 5e0ce25..94f38a6 100644 --- a/tests/test_overseerr.py +++ b/tests/test_overseerr.py @@ -223,6 +223,43 @@ async def test_search( json=None, ) +async def test_search_with_empty_tv_first_air_date( + responses: aiointercept, + client: OverseerrClient, +) -> None: + """Test searching for a TV result with an empty first air date.""" + responses.get( + f"{MOCK_URL}/search?query=unknown", + status=200, + body="""{ + "page": 1, + "totalPages": 1, + "totalResults": 1, + "results": [ + { + "id": 123, + "firstAirDate": "", + "genreIds": [], + "mediaType": "tv", + "name": "Unknown", + "originCountry": ["US"], + "originalLanguage": "en", + "originalName": "Unknown", + "overview": "", + "popularity": 0, + "voteAverage": 0, + "voteCount": 0, + "backdropPath": null, + "posterPath": null + } + ] + }""", + ) + + results = await client.search("unknown") + + assert len(results) == 1 + assert results[0].first_air_date is None async def test_search_with_encoded_spaces( responses: aiointercept, client: OverseerrClient From 1254765e9c77aeb9a5327794f349712fe941abac Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Wed, 28 Oct 2026 17:34:11 +0100 Subject: [PATCH 2/2] Fix ruff and mypy findings --- src/python_overseerr/models.py | 2 +- tests/test_overseerr.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/python_overseerr/models.py b/src/python_overseerr/models.py index fa36f69..849e559 100644 --- a/src/python_overseerr/models.py +++ b/src/python_overseerr/models.py @@ -3,7 +3,7 @@ from __future__ import annotations from dataclasses import dataclass, field -from datetime import date, datetime # noqa: TC003 +from datetime import date, datetime from enum import IntEnum, IntFlag, StrEnum from typing import Annotated diff --git a/tests/test_overseerr.py b/tests/test_overseerr.py index 94f38a6..9406104 100644 --- a/tests/test_overseerr.py +++ b/tests/test_overseerr.py @@ -18,6 +18,7 @@ OverseerrError, ) from python_overseerr.models import ( + TV, IssueStatus, IssueType, NotificationType, @@ -223,6 +224,7 @@ async def test_search( json=None, ) + async def test_search_with_empty_tv_first_air_date( responses: aiointercept, client: OverseerrClient, @@ -259,8 +261,10 @@ async def test_search_with_empty_tv_first_air_date( results = await client.search("unknown") assert len(results) == 1 + assert isinstance(results[0], TV) assert results[0].first_air_date is None + async def test_search_with_encoded_spaces( responses: aiointercept, client: OverseerrClient ) -> None: