mollie / mollie-api-python

Mollie API client for Python
http://www.mollie.com
BSD 2-Clause "Simplified" License
113 stars 55 forks source link

Client throws error for function subscriptions.get_next() #315

Closed JorikMollie closed 10 months ago

JorikMollie commented 1 year ago

Issue

When I try to get to the next page of subscriptions, using the function subscriptions.get_next() , an error is thrown.

What happens

TypeError                                 Traceback (most recent call last)
<ipython-input-5-0be7c2df0c3e> in <cell line: 10>()
      8 
      9 subscriptions = mollie_client.subscriptions.list()
---> 10 subscriptions = subscriptions.get_next() #THIS LINE THROWS ERROR

/usr/local/lib/python3.9/dist-packages/mollie/api/objects/list.py in get_next(self)
     88         """Return the next set of objects in an ObjectList."""
     89         url = self._get_link("next")
---> 90         resource = self.object_type.get_resource_class(self.client)
     91         resp = resource.perform_api_call(resource.REST_READ, url)
     92         return ObjectList(resp, self.object_type, self.client)

/usr/local/lib/python3.9/dist-packages/mollie/api/objects/subscription.py in get_resource_class(cls, client)
     10         from ..resources import CustomerSubscriptions
     11 
---> 12         return CustomerSubscriptions(client)
     13 
     14     STATUS_ACTIVE = "active"
TypeError: __init__() missing 1 required positional argument: 'customer'

What should happen

The function should retrieve the next page of subscriptions, instead of throwing that error.

Steps to reproduce

  1. Get an API key of a merchant with many subscriptions.
  2. Run this snippet of code

Import Mollie API client for python

from mollie.api.client import Client

Initialize client and set API key

mollie_client = Client() mollie_client.set_api_key(API_KEY)

subscriptions = mollie_client.subscriptions.list() subscriptions = subscriptions.get_next() #THIS LINE THROWS ERROR



### Hypothesis
The base [resource](https://github.com/mollie/mollie-api-python/blob/1114af73fd6424ea60ba862c48c868bf5d48033a/mollie/api/objects/subscription.py#L10) class for a subscription is a `CustomerSubscription` instead of a normal subscription.
whyscream commented 1 year ago

Hi @JorikMollie , thanks for reporting. We'll look into it shortly.

whyscream commented 1 year ago

Hi @JorikMollie , we discussed the issue at hand. The problem here is that subscriptions are never 'normal', but nested. All subscriptions are CustomerSubscription objects one way or another (i.e. when you retrieve a single instance of a subscription, there always is a customer id in the URL.

So the ObjectList correctly returns CustomerSubscriptions on the first pass. But when you call get_next() on that list, a new ObjectList is created for the next set of CustomerSubscriptions, which fails because the generated ObjectList is missing the required context for creating new CustomerSubscriptions (a Customer object).

This is, unforunately, a generic issue with the ObjectList implementation, and it breaks in all places where nested objects are returned by the ObjectList:

We are going to see if we can resolve this neatly in a cleaner implementation of the ObjectList class. For the time being, it could be an option to raise the number of results that a list returns by using client.subscriptions.list(limit=250), so no pagination will happen.

whyscream commented 1 year ago

This whole issue exists because we need to inject a 'parent' object into the context. The single reason to have this parent in context, is because we need its' ID to inject into the resource path. For objects that don't have a parent (f.i. payments) or objects that have a parent, but are listed outside of a parent context (f.i. client.subscriptions.list()), this problem simply doesn't exist.

To sum it up:

whyscream commented 1 year ago

@JorikMollie I have a working POC that solves this issue in https://github.com/mollie/mollie-api-python/pull/323. It works for Subscriptions AFAICS, and also for Subscription Payments (they nest two levels deep, Subscriptions only one). It needs some work, mostly just refactoring code everywhere.

whyscream commented 10 months ago

Resolved in: https://github.com/mollie/mollie-api-python/releases/tag/3.6.0