From fcf420982c57924f3639d2c34f458a86885dea18 Mon Sep 17 00:00:00 2001 From: Rob Martin Date: Sun, 4 Oct 2026 11:41:44 -0600 Subject: [PATCH] fix(googlebooks): report more pages when limit is above the 40 result page maximum --- shelfmark/metadata_providers/googlebooks.py | 6 ++++ tests/metadata/test_googlebooks_parse.py | 33 +++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/shelfmark/metadata_providers/googlebooks.py b/shelfmark/metadata_providers/googlebooks.py index 86b8174a6..1cf1bd347 100644 --- a/shelfmark/metadata_providers/googlebooks.py +++ b/shelfmark/metadata_providers/googlebooks.py @@ -7,6 +7,7 @@ """ from contextlib import suppress +from dataclasses import replace from http import HTTPStatus from typing import Any, ClassVar @@ -32,6 +33,7 @@ MetadataProvider, MetadataSearchOptions, SearchField, + SearchResult, SearchType, SortOrder, TextSearchField, @@ -217,6 +219,10 @@ def get_book(self, book_id: str) -> BookMetadata | None: ttl_default=600, key_prefix="googlebooks:isbn", ) + def search_paginated(self, options: MetadataSearchOptions) -> SearchResult: + """Google returns at most 40 per page, so a full page is 40 whatever limit asked for.""" + return super().search_paginated(replace(options, limit=min(options.limit, 40))) + def search_by_isbn(self, isbn: str) -> BookMetadata | None: """Search for a book by ISBN-10 or ISBN-13.""" # Clean ISBN (remove hyphens and spaces) diff --git a/tests/metadata/test_googlebooks_parse.py b/tests/metadata/test_googlebooks_parse.py index 2a7ad6618..b45e4b613 100644 --- a/tests/metadata/test_googlebooks_parse.py +++ b/tests/metadata/test_googlebooks_parse.py @@ -143,3 +143,36 @@ def test_parse_volume_returns_none_for_malformed_rating_payload(self): ) assert result is None + + +class _FullPageSession: + def __init__(self, count): + self.count = count + + def get(self, *args, **kwargs): + items = [ + {"id": f"v{i}", "volumeInfo": {"title": f"Book {i}", "authors": ["Alice Author"]}} + for i in range(self.count) + ] + return _GoogleBooksResponse({"items": items}) + + +def test_googlebooks_reports_more_pages_when_limit_exceeds_api_maximum(): + get_metadata_cache().clear() + provider = GoogleBooksProvider(api_key="test-key") + provider.session = _FullPageSession(40) + + result = provider.search_paginated(MetadataSearchOptions(query="Dune", limit=100)) + + assert len(result.books) == 40 + assert result.has_more is True + + +def test_googlebooks_reports_no_more_pages_after_a_short_page(): + get_metadata_cache().clear() + provider = GoogleBooksProvider(api_key="test-key") + provider.session = _FullPageSession(12) + + result = provider.search_paginated(MetadataSearchOptions(query="Dune", limit=100)) + + assert result.has_more is False