Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion stripe/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,10 @@ def list(cls, api_key=None, idempotency_key=None,
requestor = api_requestor.APIRequestor(api_key, account=stripe_account)
url = cls.class_url()
response, api_key = requestor.request('get', url, params)
return convert_to_stripe_object(response, api_key, stripe_account)
stripe_object = convert_to_stripe_object(response, api_key,
stripe_account)
stripe_object._retrieve_params = params
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I'm never a fan of assigning to "private" instance variables, I believe this is the best way to fix the current bug.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was wondering about this one too.

Here's what PEP-8 has to say about the leading underscore:

_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

In this case, _retrieve_params should be considered a property of StripeObject. Because ListObject (a descendant of StripeObject) already accesses it, we could consider its visibility to be currently "protected" (based on the definition from other OO languages). ListableAPIResource is also a descendant of StripeObject so we're not really modifying that visibility from what it was before.

The idea of protected visibility is also in-line with PEP-8's idea of internal use, so I think we're okay on this here.

return stripe_object


class CreateableAPIResource(APIResource):
Expand Down
63 changes: 39 additions & 24 deletions stripe/test/resources/test_list_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,52 +57,67 @@ def test_retrieve(self):

class AutoPagingTests(StripeApiTestCase):

def test_iter_one_page(self):
lo = stripe.resource.ListObject.construct_from({
@staticmethod
def pageable_model_response(ids, has_more):
return {
'object': 'list',
'url': '/my/path',
'data': [{'id': 'foo'}],
}, 'mykey')
'url': '/v1/pageablemodels',
'data': [{'id': id, 'object': 'pageablemodel'} for id in ids],
'has_more': has_more,
}

def test_iter_one_page(self):
lo = stripe.resource.ListObject.construct_from(
self.pageable_model_response(['pm_123', 'pm_124'], False),
'mykey'
)

self.requestor_mock.request.assert_not_called()

seen = [item['id'] for item in lo.auto_paging_iter()]

self.assertEqual(['foo'], seen)
self.assertEqual(['pm_123', 'pm_124'], seen)

def test_iter_two_pages(self):
lo = stripe.resource.ListObject.construct_from({
'object': 'list',
'url': '/my/path',
'has_more': True,
'data': [{'id': 'foo'}],
}, 'mykey')
lo = stripe.resource.ListObject.construct_from(
self.pageable_model_response(['pm_123', 'pm_124'], True),
'mykey'
)
lo._retrieve_params = {'foo': 'bar'}

self.mock_response({
'object': 'list',
'data': [{'id': 'bar'}],
'url': '/my/path',
'has_more': False,
})
self.mock_response(
self.pageable_model_response(['pm_125', 'pm_126'], False)
)

seen = [item['id'] for item in lo.auto_paging_iter()]

self.requestor_mock.request.assert_called_with(
'get', '/my/path', {'starting_after': 'foo'}, None)
'get',
'/v1/pageablemodels',
{
'starting_after': 'pm_124',
'foo': 'bar'
},
None
)

self.assertEqual(['foo', 'bar'], seen)
self.assertEqual(['pm_123', 'pm_124', 'pm_125', 'pm_126'], seen)

def test_class_method_two_pages(self):
self.mock_response({
'object': 'list',
'data': [{'id': 'bar'}],
'data': [{'id': 'ch_001'}],
'url': '/v1/charges',
'has_more': False,
})

seen = [i['id'] for i in stripe.Charge.auto_paging_iter(limit=25)]
seen = [item['id'] for item in stripe.Charge.auto_paging_iter(
limit=25,
foo='bar'
)]

self.requestor_mock.request.assert_called_with(
'get', '/v1/charges', {'limit': 25})
'get', '/v1/charges', {'limit': 25, 'foo': 'bar'}
)

self.assertEqual(['bar'], seen)
self.assertEqual(['ch_001'], seen)
36 changes: 21 additions & 15 deletions stripe/test/resources/test_listable.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,29 @@
class ListableAPIResourceTests(StripeApiTestCase):

def test_all(self):
self.mock_response([
{
'object': 'charge',
'name': 'jose',
},
{
'object': 'charge',
'name': 'curly',
}
])
self.mock_response({
'object': 'list',
'data': [
{
'object': 'charge',
'name': 'jose',
},
{
'object': 'charge',
'name': 'curly',
}
],
'url': '/v1/charges',
'has_more': False,
})

res = MyListable.all()
res = MyListable.list()

self.requestor_mock.request.assert_called_with(
'get', '/v1/mylistables', {})

self.assertEqual(2, len(res))
self.assertTrue(all(isinstance(obj, stripe.Charge) for obj in res))
self.assertEqual('jose', res[0].name)
self.assertEqual('curly', res[1].name)
self.assertEqual(2, len(res.data))
self.assertTrue(all(isinstance(obj, stripe.Charge)
for obj in res.data))
self.assertEqual('jose', res.data[0].name)
self.assertEqual('curly', res.data[1].name)