Skip to content

Commit e6ee44f

Browse files
authored
[fix] Remove bad post-request guard clause in pagination functions (#303)
- Remove bad post-request guard clause causing pagination functions to never return the final page of results - Add unit test to beta user children pagination tests to verify pagination function works as expected (allows iteration over all available pages)
1 parent 6d6065c commit e6ee44f

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

easypost/beta/user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def get_next_page_of_children(
4545

4646
data, api_key = requestor.request(method=RequestMethod.GET, url=url, params=params, beta=True)
4747
next_children_array: List[Any] = data.get("children", [])
48-
if len(next_children_array) == 0 or not data.get("has_more", False):
48+
if len(next_children_array) == 0:
4949
raise Error(message="There are no more pages to retrieve.")
5050

5151
return convert_to_easypost_object(response=data, api_key=api_key)

easypost/resource.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def get_next_page(
9393

9494
response, api_key = requestor.request(method=RequestMethod.GET, url=url, params=params)
9595
response_array: List[Any] = response.get(url[1:]) # type: ignore
96-
if response is None or len(response_array) == 0 or not response.get("has_more"):
96+
if response is None or len(response_array) == 0:
9797
raise Error(message="There are no more pages to retrieve.")
9898

9999
return convert_to_easypost_object(response=response, api_key=api_key)

tests/cassettes/test_beta_user_get_next_page_collect_all.yaml

Lines changed: 67 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/test_beta_user.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from unittest.mock import patch
2+
13
import pytest
24

35
import easypost
@@ -28,3 +30,73 @@ def test_beta_user_get_next_page(prod_api_key, page_size):
2830
except easypost.Error as e:
2931
if e.message != "There are no more pages to retrieve.":
3032
raise easypost.Error(message="Test failed intentionally.")
33+
34+
35+
@pytest.mark.vcr() # Cassette not needed due to mocking, but used to avoid making real bogus API calls
36+
def test_beta_user_get_next_page_collect_all(prod_api_key):
37+
page_size = 1 # Doesn't matter what this is, we're mocking the response
38+
all_children = []
39+
40+
first_page_response = {
41+
"children": [
42+
{
43+
"id": "user_123",
44+
}
45+
],
46+
"has_more": True,
47+
}
48+
49+
# Mock the initial "get all children" call
50+
return_value = (first_page_response, prod_api_key)
51+
with patch("easypost.requestor.Requestor.request", return_value=return_value):
52+
first_page = easypost.beta.User.all_children(page_size=page_size)
53+
all_children += first_page["children"]
54+
previous_page = first_page
55+
56+
second_page_response = {
57+
"children": [
58+
{
59+
"id": "user_456",
60+
}
61+
],
62+
"has_more": True,
63+
}
64+
65+
# Mock the first "get next page" call with more to collect after
66+
# (current page "has_more" = True, next page "has_more" = True)
67+
return_value = (second_page_response, prod_api_key)
68+
with patch("easypost.requestor.Requestor.request", return_value=return_value):
69+
next_page = easypost.beta.User.get_next_page_of_children(
70+
children=previous_page, page_size=page_size # type: ignore
71+
)
72+
all_children += next_page["children"]
73+
previous_page = next_page
74+
75+
third_page_response = {
76+
"children": [
77+
{
78+
"id": "user_789",
79+
}
80+
],
81+
"has_more": False,
82+
}
83+
84+
# Mock the second "get next page" call with no more to collect
85+
# (current page "has_more" = True, next page "has_more" = False)
86+
return_value = (third_page_response, prod_api_key)
87+
with patch("easypost.requestor.Requestor.request", return_value=return_value):
88+
next_page = easypost.beta.User.get_next_page_of_children(
89+
children=previous_page, page_size=page_size # type: ignore
90+
)
91+
all_children += next_page["children"]
92+
previous_page = next_page
93+
94+
# Verify we have all children (from both the "get all children" and "get next page" calls)
95+
# Ensures that no guard clauses inside the "get next page" method are preventing us from collecting all children
96+
assert len(all_children) == 3
97+
98+
# Now that the previous page has "has_more" = False, it should throw an error before even making the API call
99+
with pytest.raises(easypost.Error) as error:
100+
_ = easypost.beta.User.get_next_page_of_children(children=previous_page, page_size=page_size) # type: ignore
101+
102+
assert str(error.value) == "There are no more pages to retrieve."

0 commit comments

Comments
 (0)