Skip to content

Commit dc9a0a8

Browse files
committed
adds tests for the pagination feature
1 parent 8c29819 commit dc9a0a8

36 files changed

Lines changed: 2643 additions & 617 deletions

apimatic_core/pagination/paginated_data.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ def __init__(self, api_call, paginated_items_converter):
5757
self._api_call.global_configuration.get_http_client_configuration().http_callback or HttpCallContext()
5858
_http_client_configuration = self._api_call.global_configuration.get_http_client_configuration().clone(
5959
http_callback=self._http_call_context)
60-
self._global_configuration = self._api_call.global_configuration.clone_with(
61-
http_client_configuration=_http_client_configuration)
60+
self._global_configuration = self._api_call.global_configuration.clone_with()
6261
self._paged_response = None
6362
self._items = []
6463
self._page_size = 0
@@ -82,7 +81,8 @@ def __next__(self):
8281
return item
8382

8483
self._paged_response = self._fetch_next_page()
85-
self._items = self._paginated_items_converter(self._paged_response.body)
84+
self._items = self._paginated_items_converter(
85+
self._paged_response.body) if self._paged_response else []
8686
if not self._items:
8787
raise StopIteration
8888
self._page_size, self._current_index = len(self._items), 0
@@ -102,7 +102,8 @@ def pages(self):
102102

103103
while True:
104104
paginated_data._paged_response = paginated_data._fetch_next_page()
105-
paginated_data._items = self._paginated_items_converter(paginated_data._paged_response.body)
105+
paginated_data._items = self._paginated_items_converter(
106+
paginated_data._paged_response.body) if paginated_data._paged_response else []
106107
if not paginated_data._items:
107108
break
108109
paginated_data._page_size = len(paginated_data._items)
@@ -132,7 +133,7 @@ def _fetch_next_page(self):
132133
).execute()
133134
return pagination_strategy.apply_metadata_wrapper(response)
134135

135-
return []
136+
return None
136137

137138
def _get_new_self_instance(self):
138139
"""

apimatic_core/pagination/pagination_strategy.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,32 @@ def get_updated_request_builder(request_builder, input_pointer, offset):
8282
header_params = ApiHelper.update_entry_by_json_pointer(
8383
header_params.copy(), field_path, offset, inplace=True)
8484

85-
return request_builder.clone_with(
86-
template_params=template_params,
87-
query_params=query_params,
88-
header_params=header_params
89-
)
85+
return request_builder.clone_with(template_params=template_params, query_params=query_params,
86+
header_params=header_params)
87+
88+
@staticmethod
89+
def _get_initial_request_param_value(request_builder, input_pointer, default=0):
90+
"""
91+
Extracts the initial pagination offset value from the request builder using the specified JSON pointer.
92+
93+
Args:
94+
request_builder: The request builder containing path, query, and header parameters.
95+
input_pointer (str): JSON pointer indicating which parameter to extract.
96+
default (int, optional): The value to return if the parameter is not found. Defaults to 0.
97+
98+
Returns:
99+
int: The initial offset value from the specified parameter, or default if not found.
100+
"""
101+
path_prefix, field_path = ApiHelper.split_into_parts(input_pointer)
102+
103+
if path_prefix == "$request.path":
104+
value = ApiHelper.get_value_by_json_pointer(request_builder.template_params, field_path)
105+
return int(value) if value is not None else default
106+
elif path_prefix == "$request.query":
107+
value = ApiHelper.get_value_by_json_pointer(request_builder.query_params, field_path)
108+
return int(value) if value is not None else default
109+
elif path_prefix == "$request.headers":
110+
value = ApiHelper.get_value_by_json_pointer(request_builder.header_params, field_path)
111+
return int(value) if value is not None else default
112+
113+
return default

apimatic_core/pagination/strategies/link_pagination.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,7 @@ def apply(self, paginated_data):
6161
updated_query_params = request_builder.query_params.copy()
6262
updated_query_params.update(query_params)
6363

64-
return request_builder.clone_with(
65-
query_params=updated_query_params
66-
)
64+
return request_builder.clone_with(query_params=updated_query_params)
6765

6866
def apply_metadata_wrapper(self, paged_response):
6967
"""

apimatic_core/pagination/strategies/offset_pagination.py

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def apply(self, paginated_data):
4949
last_page_size = paginated_data.page_size
5050
# The last response is none which means this is going to be the 1st page
5151
if last_response is None:
52-
self._offset = self._get_initial_offset(request_builder)
52+
self._offset = self._get_initial_request_param_value(request_builder, self._input)
5353
return request_builder
5454

5555
self._offset += last_page_size
@@ -67,25 +67,3 @@ def apply_metadata_wrapper(self, page_response):
6767
The result of the metadata wrapper callable with the page response and offset.
6868
"""
6969
return self._metadata_wrapper(page_response, self._offset)
70-
71-
def _get_initial_offset(self, request_builder):
72-
"""
73-
Determines the initial offset value for pagination by extracting it from the request builder
74-
based on the configured JSON pointer input.
75-
76-
Args:
77-
request_builder: The request builder containing path, query, and header parameters.
78-
79-
Returns:
80-
int: The initial offset value extracted from the appropriate request parameter, or 0 if not found.
81-
"""
82-
path_prefix, field_path = ApiHelper.split_into_parts(self._input)
83-
84-
if path_prefix == "$request.path":
85-
return int(ApiHelper.get_value_by_json_pointer(request_builder.template_params, field_path))
86-
elif path_prefix == "$request.query":
87-
return int(ApiHelper.get_value_by_json_pointer(request_builder.query_params, field_path))
88-
elif path_prefix == "$request.headers":
89-
return int(ApiHelper.get_value_by_json_pointer(request_builder.header_params, field_path))
90-
91-
return 0

apimatic_core/pagination/strategies/page_pagination.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def apply(self, paginated_data):
4444
last_page_size = paginated_data.page_size
4545
# The last response is none which means this is going to be the 1st page
4646
if last_response is None:
47-
self._page_number = self._get_initial_page_offset(request_builder)
47+
self._page_number = self._get_initial_request_param_value(request_builder, self._input, 1)
4848
return request_builder
4949
self._page_number += 1 if last_page_size > 0 else 0
5050

@@ -61,27 +61,3 @@ def apply_metadata_wrapper(self, paged_response):
6161
The result of the metadata wrapper with the paged response and current page number.
6262
"""
6363
return self._metadata_wrapper(paged_response, self._page_number)
64-
65-
def _get_initial_page_offset(self, request_builder):
66-
"""
67-
Determines the initial page offset for pagination by extracting the value from the request builder
68-
based on the configured JSON pointer. Returns 1 if the value is missing or invalid.
69-
70-
Args:
71-
request_builder: The request builder containing path, query, and header parameters.
72-
73-
Returns:
74-
int: The initial page offset value.
75-
"""
76-
path_prefix, field_path = ApiHelper.split_into_parts(self._input)
77-
78-
try:
79-
if path_prefix == "$request.path":
80-
return int(ApiHelper.get_value_by_json_pointer(request_builder.template_params, field_path))
81-
elif path_prefix == "$request.query":
82-
return int(ApiHelper.get_value_by_json_pointer(request_builder.query_params, field_path))
83-
elif path_prefix == "$request.headers":
84-
return int(ApiHelper.get_value_by_json_pointer(request_builder.header_params, field_path))
85-
except ValueError:
86-
pass
87-
return 1

apimatic_core/request_builder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def apply_auth(self, auth_managers, http_request):
230230
raise AuthValidationException(self._auth.error_message)
231231

232232
def clone_with(
233-
self, template_params=None, header_params=None, query_params=None, form_params=None
233+
self, template_params=None, header_params=None, query_params=None
234234
):
235235
"""
236236
Clone the current instance with the given parameters.
@@ -251,7 +251,7 @@ def clone_with(
251251
new_instance._template_params = template_params or self._template_params
252252
new_instance._header_params = header_params or self._header_params
253253
new_instance._query_params = query_params or self._query_params
254-
new_instance._form_params = form_params or self._form_params
254+
new_instance._form_params = self._form_params
255255
new_instance._additional_form_params = self._additional_form_params
256256
new_instance._additional_query_params = self._additional_query_params
257257
new_instance._multipart_params = self._multipart_params

apimatic_core/utilities/api_helper.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,10 @@ def get_value_by_json_pointer(dictionary, pointer):
818818
Raises:
819819
JsonPointerException: If the pointer does not resolve to a value.
820820
"""
821-
return resolve_pointer(dictionary, pointer)
821+
try:
822+
return resolve_pointer(dictionary, pointer)
823+
except JsonPointerException as jpe:
824+
return None
822825

823826
class CustomDate(object):
824827

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pytest~=7.2.2
2+
pytest-mock~=3.14.0
23
coverage~=7.2.2
34
testfixtures~=8.2.0

0 commit comments

Comments
 (0)