Skip to content

Commit 3555afc

Browse files
committed
fix: add trust_per_page config option to toggle sequential page walk
fix: add trust_per_page config, update __getitem__ and tests accordingly fix: add trust_per_page config, update __getitem__ and tests accordingly#
1 parent eabf016 commit 3555afc

3 files changed

Lines changed: 42 additions & 13 deletions

File tree

discogs_client/client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def __init__(self, user_agent, consumer_key=None, consumer_secret=None, token=No
1919
self.user_agent = user_agent
2020
self.verbose = False
2121
self._fetcher = RequestsFetcher()
22+
self._trust_per_page = True # Default: True
2223

2324
if consumer_key and consumer_secret:
2425
self.set_consumer_key(consumer_key, consumer_secret)
@@ -219,3 +220,13 @@ def set_timeout(self,
219220
"""
220221
self._fetcher.connect_timeout = connect
221222
self._fetcher.read_timeout = read
223+
224+
@property
225+
def trust_per_page(self) -> bool:
226+
return self._trust_per_page
227+
228+
@trust_per_page.setter
229+
def trust_per_page(self, value: bool) -> None:
230+
if not isinstance(value, bool):
231+
raise ValueError("trust_per_page must be a bool")
232+
self._trust_per_page = value

discogs_client/models.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -354,26 +354,40 @@ def _transform(self, item):
354354
return item
355355

356356
def __getitem__(self, index):
357-
# Rather than trusting per_page metadata for offset math, we walk
358-
# through actual page sizes sequentially. This handles cases where
359-
# Discogs returns fewer items than per_page claims, which causes
360-
# index-out-of-range errors when using the standard calculation:
361-
# page_index = index // self.per_page + 1
362-
# offset = index % self.per_page
363-
current = 0
364-
page_index = 1
365-
while True:
357+
if self.client._trust_per_page:
358+
# Directly jump to index using offset math.
359+
# Default
360+
page_index = index // self.per_page + 1
361+
offset = index % self.per_page
362+
366363
try:
367364
page = self.page(page_index)
368365
except HTTPError as e:
369366
if e.status_code == 404:
370367
raise IndexError(e.msg)
371368
else:
372369
raise
373-
if current + len(page) > index:
374-
return page[index - current]
375-
current += len(page)
376-
page_index += 1
370+
371+
return page[offset]
372+
373+
else:
374+
# Sequentially walks through each page until index or end of array reached.
375+
# Opt-in
376+
current = 0
377+
page_index = 1
378+
while True:
379+
try:
380+
page = self.page(page_index)
381+
except HTTPError as e:
382+
if e.status_code == 404:
383+
raise IndexError(e.msg)
384+
else:
385+
raise
386+
if current + len(page) > index:
387+
return page[index - current]
388+
current += len(page)
389+
page_index += 1
390+
377391

378392
def __len__(self):
379393
return self.count

discogs_client/tests/test_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ def test_pagination(self):
114114
def test_pagination_with_short_page(self):
115115
"""Indexing walks actual page sizes when the API under-fills a page."""
116116
client = Client('ua')
117+
client.trust_per_page = False # opt into sequential walk
117118
client._base_url = ''
118119
client._fetcher = MemoryFetcher({
119120
'/artists/1': (
@@ -143,6 +144,7 @@ def test_pagination_with_short_page(self):
143144
def test_pagination_with_varying_page_sizes(self):
144145
"""Indexing works correctly with pages of different actual sizes."""
145146
client = Client('ua')
147+
client.trust_per_page = False # opt into sequential walk
146148
client._base_url = ''
147149
client._fetcher = MemoryFetcher({
148150
'/artists/1': (
@@ -194,6 +196,7 @@ def test_pagination_with_varying_page_sizes(self):
194196
def test_pagination_with_short_page_sequential_traversal(self):
195197
"""Verify sequential page walking works when all pages are short."""
196198
client = Client('ua')
199+
client.trust_per_page = False # opt into sequential walk
197200
client._base_url = ''
198201
client._fetcher = MemoryFetcher({
199202
'/artists/1': (
@@ -235,6 +238,7 @@ def test_pagination_with_short_page_sequential_traversal(self):
235238
def test_pagination_404_exception_chaining(self):
236239
"""Verify that HTTPError 404 is properly chained when index is out of bounds."""
237240
client = Client('ua')
241+
client.trust_per_page = False # opt into sequential walk
238242
client._base_url = ''
239243
client._fetcher = MemoryFetcher({
240244
'/artists/1': (

0 commit comments

Comments
 (0)