1- from . base import ObjectBase
2-
1+ from abc import ABC , abstractmethod
2+ from typing import TYPE_CHECKING , Any , Optional , Type
33
4- class UnknownObject (ObjectBase ):
5- """Mock object for empty lists."""
4+ from .base import ObjectBase
65
7- @ classmethod
8- def get_object_name ( cls ):
9- return "unknown"
6+ if TYPE_CHECKING :
7+ from mollie . api . client import Client
8+ from mollie . api . resources . base import ResourceBase
109
1110
12- class ObjectList (ObjectBase ):
11+ class ListBase (ObjectBase , ABC ):
1312 current = None
1413
15- def __init__ (self , result , object_type , client = None ):
16- # If an empty dataset was injected, we mock the structure that the remainder of the clas expects.
17- # TODO: it would be better if the ObjectList was initiated with a list of results, rather than with
18- # the full datastructure as it is now, so we can remove all this mucking around with fake data,
19- # mocked result objects, and loads of lengthy accessor workarounds everywhere in the ObjectList.
20- if result == {}:
21- result = {"_embedded" : {"unknown" : []}, "count" : 0 }
22- object_type = UnknownObject
23-
24- super ().__init__ (result , client )
25- self .object_type = object_type
26-
2714 def __len__ (self ):
2815 """Return the count field."""
2916 return self .count
@@ -66,7 +53,7 @@ def __getitem__(self, key):
6653 },
6754 "count" : len (sliced_data ),
6855 }
69- return ObjectList ( sliced_result , self .object_type , self . client )
56+ return self .new ( sliced_result )
7057
7158 return super ().__getitem__ (key )
7259
@@ -84,16 +71,101 @@ def has_previous(self):
8471 """Return True if the ObjectList contains an url for the previous set."""
8572 return self ._get_link ("previous" ) is not None
8673
74+ @abstractmethod
8775 def get_next (self ):
88- """Return the next set of objects in an ObjectList."""
76+ ...
77+
78+ @abstractmethod
79+ def get_previous (self ):
80+ ...
81+
82+ @property
83+ @abstractmethod
84+ def object_type (self ):
85+ ...
86+
87+ @abstractmethod
88+ def new (self , result ):
89+ ...
90+
91+
92+ class PaginationList (ListBase ):
93+ """
94+ Pagination lists are used to return a paginated list of Objects.
95+
96+ You can use the `has_next` and `get_next` methods to get the next page of result data from the API.
97+ The `has_previous` and `get_previous` methods return the previous page.
98+ """
99+
100+ _parent : "ResourceBase"
101+
102+ def __init__ (self , result : Any , parent : "ResourceBase" , client : "Client" ):
103+ # If an empty dataset was injected, we mock the structure that the remainder of the clas expects.
104+ # TODO: it would be better if the ObjectList was initiated with a list of results, rather than with
105+ # the full datastructure as it is now, so we can remove all this mucking around with fake data,
106+ # mocked result objects, and loads of lengthy accessor workarounds everywhere in the ObjectList.
107+ self ._parent = parent
108+
109+ if result == {}:
110+ result = {"_embedded" : {f"{ self ._parent .object_type .get_object_name ()} " : []}, "count" : 0 }
111+
112+ super ().__init__ (result , client )
113+
114+ def get_next (self ):
115+ """Return the next set of objects in the paginated list."""
89116 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 )
117+ if url is None :
118+ return None
119+ resp = self ._parent .perform_api_call (self ._parent .REST_READ , url )
120+ return PaginationList (resp , self ._parent , self .client )
93121
94122 def get_previous (self ):
95- """Return the previous set of objects in an ObjectList ."""
123+ """Return the previous set of objects in the paginated list ."""
96124 url = self ._get_link ("previous" )
97- resource = self .object_type .get_resource_class (self .client )
98- resp = resource .perform_api_call (resource .REST_READ , url )
99- return ObjectList (resp , self .object_type , self .client )
125+ if url is None :
126+ return None
127+ resp = self ._parent .perform_api_call (self ._parent .REST_READ , url )
128+ return PaginationList (resp , self ._parent , self .client )
129+
130+ @property
131+ def object_type (self ):
132+ return self ._parent .object_type
133+
134+ def new (self , result ):
135+ return PaginationList (result , self ._parent , self .client )
136+
137+
138+ class ObjectList (ListBase ):
139+ """
140+ Object lists are used to return an embedded list on an object.
141+
142+ It works to similar to PaginationList, but has no pagination (as all data is already embedded).
143+ """
144+
145+ _object_type : Type [ObjectBase ]
146+
147+ def __init__ (self , result : Any , object_type : Type [ObjectBase ], client : Optional ["Client" ] = None ):
148+ # If an empty dataset was injected, we mock the structure that the remainder of the clas expects.
149+ # TODO: it would be better if the ObjectList was initiated with a list of results, rather than with
150+ # the full datastructure as it is now, so we can remove all this mucking around with fake data,
151+ # mocked result objects, and loads of lengthy accessor workarounds everywhere in the ObjectList.
152+ self ._object_type = object_type
153+
154+ if result == {}:
155+ result = {"_embedded" : {f"{ self ._object_type .get_object_name ()} " : []}, "count" : 0 }
156+
157+ super ().__init__ (result , client )
158+
159+ def get_next (self ):
160+ """Return the next set of objects in an ObjectList."""
161+ return None
162+
163+ def get_previous (self ):
164+ return None
165+
166+ @property
167+ def object_type (self ):
168+ return self ._object_type
169+
170+ def new (self , result ):
171+ return ObjectList (result , self ._object_type , self .client )
0 commit comments