Skip to content

Commit 964fe74

Browse files
committed
style: Tidy pagination test helper names and normalize non-ASCII chars
1 parent e81c2a9 commit 964fe74

2 files changed

Lines changed: 29 additions & 29 deletions

File tree

src/apify_client/_pagination.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
class HasItems(Protocol[T]):
2020
"""Structural contract for a single page of results from a paginated API endpoint.
2121
22-
Implementations must expose `items`. They may optionally expose `count` the number of items scanned by the API for
22+
Implementations must expose `items`. They may optionally expose `count` - the number of items scanned by the API for
2323
this page, which can exceed `len(items)` when filters drop items from the response. The iterator helpers consult
2424
`count` opportunistically via `getattr` for offset bookkeeping and fall back to `len(items)` when it is absent.
2525
"""
@@ -42,8 +42,8 @@ def get_items_iterator(
4242
filters are applied).
4343
4444
Iteration stops when a page scans no items (`count` is `0`, or `items` is empty when `count` is absent) or when the
45-
user-requested `limit` is reached. A page can scan items while returning none filters like `clean` drop items from
46-
`items` but still count toward `count` so terminating on scanned rather than returned items keeps the iterator
45+
user-requested `limit` is reached. A page can scan items while returning none - filters like `clean` drop items from
46+
`items` but still count toward `count` - so terminating on scanned rather than returned items keeps the iterator
4747
advancing across fully-filtered pages. The `total` field is intentionally not consulted, because it can change
4848
between calls.
4949

tests/unit/test_client_pagination.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
)
120120

121121
# Outer wrappers that embed a relaxed list model via `.data`. Their compiled schema pins the inner's schema at
122-
# construction time, so they need a forced rebuild to pick up the relaxation. The wrappers themselves are not mutated
122+
# construction time, so they need a forced rebuild to pick up the relaxation. The wrappers themselves are not mutated -
123123
# their own field annotations stay as-is.
124124
_REBUILT_RESPONSE_WRAPPERS = (
125125
'ListOfActorsInStoreResponse',
@@ -144,9 +144,9 @@ def _relax_item_validation() -> Any:
144144
"""Relax only the element type of `items` on paginated list models for the test run.
145145
146146
Pagination tests feed synthetic `{'id': N}` items that don't satisfy the real API schemas (`ActorShort`,
147-
`BuildShort`, `Request`, `EnvVar`, ). Instead of bypassing validation wholesale, each inner `ListOf*` model has its
148-
`items` field swapped to `list[dict]` and rebuilt. Outer `.data` wrapping and every pagination-metadata field remain
149-
validated.
147+
`BuildShort`, `Request`, `EnvVar`, ...). Instead of bypassing validation wholesale, each inner `ListOf*` model
148+
has its `items` field swapped to `list[dict]` and rebuilt. Outer `.data` wrapping and every pagination-metadata
149+
field remain validated.
150150
"""
151151
relaxed_field = FieldInfo.from_annotation(list[dict])
152152
originals: dict[type[BaseModel], FieldInfo] = {}
@@ -177,7 +177,7 @@ def create_items(start: int, end: int, step: int | None = None) -> list[dict[str
177177

178178

179179
def _is_true(value: str | None) -> bool:
180-
"""Match the `'true'` wire form produced by the client's boolstring serialization."""
180+
"""Match the `'true'` wire form produced by the client's bool->string serialization."""
181181
return value == 'true'
182182

183183

@@ -241,7 +241,7 @@ def _handle_cursor_pagination(request: Request) -> Response:
241241
"""Serve a cursor-paginated Apify API response for KVS keys and RQ requests.
242242
243243
Holds 2500 synthetic items whose integer `id` equals their position. Each page is capped at 1000 items. KVS uses
244-
`exclusiveStartKey`; RQ uses the opaque `cursor`. Both values encode the last-seen item id as a string the
244+
`exclusiveStartKey`; RQ uses the opaque `cursor`. Both values encode the last-seen item id as a string - the
245245
next page starts at id + 1.
246246
"""
247247
params = request.args
@@ -625,15 +625,15 @@ async def test_rq_list_requests_iterable_async(
625625
assert returned_items == expected_items
626626

627627

628-
class _FakeOffsetPage:
628+
class FakeOffsetPage:
629629
"""Offset-paginated page whose `count` (items scanned) may exceed `len(items)` when filters drop items."""
630630

631631
def __init__(self, items: list[dict[str, int]], count: int) -> None:
632632
self.items = items
633633
self.count = count
634634

635635

636-
class _FakeCursorPage:
636+
class FakeCursorPage:
637637
"""Cursor-paginated page mirroring `ListOfRequests`: no scanned-`count`, so a filtered page is just `items=[]`."""
638638

639639
def __init__(self, items: list[dict[str, int]], next_cursor: str | None) -> None:
@@ -644,51 +644,51 @@ def __init__(self, items: list[dict[str, int]], next_cursor: str | None) -> None
644644
def test_items_iterator_continues_past_fully_filtered_page() -> None:
645645
"""A fully-filtered page (`items=[]`, `count>0`) must not stop the offset iterator while more data was scanned."""
646646
pages = {
647-
0: _FakeOffsetPage(items=[], count=1000),
648-
1000: _FakeOffsetPage(items=[{'id': 1}, {'id': 2}], count=2),
647+
0: FakeOffsetPage(items=[], count=1000),
648+
1000: FakeOffsetPage(items=[{'id': 1}, {'id': 2}], count=2),
649649
}
650650

651-
def _callback(*, limit: int | None = None, offset: int | None = None) -> _FakeOffsetPage: # noqa: ARG001
652-
return pages.get(offset or 0, _FakeOffsetPage(items=[], count=0))
651+
def callback(*, limit: int | None = None, offset: int | None = None) -> FakeOffsetPage: # noqa: ARG001
652+
return pages.get(offset or 0, FakeOffsetPage(items=[], count=0))
653653

654-
assert list(get_items_iterator(_callback, chunk_size=1000)) == [{'id': 1}, {'id': 2}]
654+
assert list(get_items_iterator(callback, chunk_size=1000)) == [{'id': 1}, {'id': 2}]
655655

656656

657657
async def test_items_iterator_async_continues_past_fully_filtered_page() -> None:
658658
"""A fully-filtered page (`items=[]`, `count>0`) must not stop the async offset iterator while more was scanned."""
659659
pages = {
660-
0: _FakeOffsetPage(items=[], count=1000),
661-
1000: _FakeOffsetPage(items=[{'id': 1}, {'id': 2}], count=2),
660+
0: FakeOffsetPage(items=[], count=1000),
661+
1000: FakeOffsetPage(items=[{'id': 1}, {'id': 2}], count=2),
662662
}
663663

664-
async def _callback(*, limit: int | None = None, offset: int | None = None) -> _FakeOffsetPage: # noqa: ARG001
665-
return pages.get(offset or 0, _FakeOffsetPage(items=[], count=0))
664+
async def callback(*, limit: int | None = None, offset: int | None = None) -> FakeOffsetPage: # noqa: ARG001
665+
return pages.get(offset or 0, FakeOffsetPage(items=[], count=0))
666666

667-
assert [item async for item in get_items_iterator_async(_callback, chunk_size=1000)] == [{'id': 1}, {'id': 2}]
667+
assert [item async for item in get_items_iterator_async(callback, chunk_size=1000)] == [{'id': 1}, {'id': 2}]
668668

669669

670670
def test_cursor_iterator_continues_past_fully_filtered_page() -> None:
671671
"""A fully-filtered page (`items=[]`) with a live cursor must not stop the cursor iterator."""
672672
pages = {
673-
None: _FakeCursorPage(items=[], next_cursor='c1'),
674-
'c1': _FakeCursorPage(items=[{'id': 1}, {'id': 2}], next_cursor=None),
673+
None: FakeCursorPage(items=[], next_cursor='c1'),
674+
'c1': FakeCursorPage(items=[{'id': 1}, {'id': 2}], next_cursor=None),
675675
}
676676

677-
def _callback(*, limit: int | None = None, cursor: str | None = None) -> _FakeCursorPage: # noqa: ARG001
677+
def callback(*, limit: int | None = None, cursor: str | None = None) -> FakeCursorPage: # noqa: ARG001
678678
return pages[cursor]
679679

680-
assert list(get_cursor_iterator(_callback, chunk_size=1000)) == [{'id': 1}, {'id': 2}] # ty: ignore[no-matching-overload]
680+
assert list(get_cursor_iterator(callback, chunk_size=1000)) == [{'id': 1}, {'id': 2}] # ty: ignore[no-matching-overload]
681681

682682

683683
async def test_cursor_iterator_async_continues_past_fully_filtered_page() -> None:
684684
"""A fully-filtered page (`items=[]`) with a live cursor must not stop the async cursor iterator."""
685685
pages = {
686-
None: _FakeCursorPage(items=[], next_cursor='c1'),
687-
'c1': _FakeCursorPage(items=[{'id': 1}, {'id': 2}], next_cursor=None),
686+
None: FakeCursorPage(items=[], next_cursor='c1'),
687+
'c1': FakeCursorPage(items=[{'id': 1}, {'id': 2}], next_cursor=None),
688688
}
689689

690-
async def _callback(*, limit: int | None = None, cursor: str | None = None) -> _FakeCursorPage: # noqa: ARG001
690+
async def callback(*, limit: int | None = None, cursor: str | None = None) -> FakeCursorPage: # noqa: ARG001
691691
return pages[cursor]
692692

693-
collected = [item async for item in get_cursor_iterator_async(_callback, chunk_size=1000)] # ty: ignore[no-matching-overload]
693+
collected = [item async for item in get_cursor_iterator_async(callback, chunk_size=1000)] # ty: ignore[no-matching-overload]
694694
assert collected == [{'id': 1}, {'id': 2}]

0 commit comments

Comments
 (0)