55
66import httpx
77
8- from mpt_api_client .http .client import MPTClient
8+ from mpt_api_client .http .client import HTTPClient
9+ from mpt_api_client .http .resource import ResourceBaseClient
910from mpt_api_client .models import Collection , Resource
1011from mpt_api_client .rql .query_builder import RQLQuery
1112
1213
13- class CollectionBaseClient [ResourceType : Resource ](ABC ): # noqa: WPS214
14+ class CollectionBaseClient [ResourceModel : Resource , ResourceClient : ResourceBaseClient [Resource ]]( # noqa: WPS214
15+ ABC
16+ ):
1417 """Immutable Base client for RESTful resource collections.
1518
1619 Examples:
@@ -23,21 +26,24 @@ class CollectionBaseClient[ResourceType: Resource](ABC): # noqa: WPS214
2326 """
2427
2528 _endpoint : str
26- _resource_class : type [ResourceType ]
27- _collection_class : type [Collection [ResourceType ]]
29+ _resource_class : type [ResourceModel ]
30+ _resource_client_class : type [ResourceClient ]
31+ _collection_class : type [Collection [ResourceModel ]]
2832
2933 def __init__ (
3034 self ,
3135 query_rql : RQLQuery | None = None ,
32- client : MPTClient | None = None ,
36+ client : HTTPClient | None = None ,
3337 ) -> None :
34- self .mpt_client = client or MPTClient ()
38+ self .mpt_client = client or HTTPClient ()
3539 self .query_rql : RQLQuery | None = query_rql
3640 self .query_order_by : list [str ] | None = None
3741 self .query_select : list [str ] | None = None
3842
3943 @classmethod
40- def clone (cls , collection_client : "CollectionBaseClient[ResourceType]" ) -> Self :
44+ def clone (
45+ cls , collection_client : "CollectionBaseClient[ResourceModel, ResourceClient]"
46+ ) -> Self :
4147 """Create a copy of collection client for immutable operations.
4248
4349 Returns:
@@ -122,7 +128,7 @@ def select(self, *fields: str) -> Self:
122128 new_client .query_select = list (fields )
123129 return new_client
124130
125- def fetch_page (self , limit : int = 100 , offset : int = 0 ) -> Collection [ResourceType ]:
131+ def fetch_page (self , limit : int = 100 , offset : int = 0 ) -> Collection [ResourceModel ]:
126132 """Fetch one page of resources.
127133
128134 Returns:
@@ -131,7 +137,7 @@ def fetch_page(self, limit: int = 100, offset: int = 0) -> Collection[ResourceTy
131137 response = self ._fetch_page_as_response (limit = limit , offset = offset )
132138 return Collection .from_response (response )
133139
134- def fetch_one (self ) -> ResourceType :
140+ def fetch_one (self ) -> ResourceModel :
135141 """Fetch one page, expect exactly one result.
136142
137143 Returns:
@@ -141,7 +147,7 @@ def fetch_one(self) -> ResourceType:
141147 ValueError: If the total matching records are not exactly one.
142148 """
143149 response = self ._fetch_page_as_response (limit = 1 , offset = 0 )
144- resource_list : Collection [ResourceType ] = Collection .from_response (response )
150+ resource_list : Collection [ResourceModel ] = Collection .from_response (response )
145151 total_records = len (resource_list )
146152 if resource_list .meta :
147153 total_records = resource_list .meta .pagination .total
@@ -152,18 +158,23 @@ def fetch_one(self) -> ResourceType:
152158
153159 return resource_list [0 ]
154160
155- def iterate (self ) -> Iterator [ResourceType ]:
161+ def iterate (self , batch_size : int = 100 ) -> Iterator [ResourceModel ]:
156162 """Iterate over all resources, yielding GenericResource objects.
157163
164+ Args:
165+ batch_size: Number of resources to fetch per request
166+
158167 Returns:
159168 Iterator of resources.
160169 """
161170 offset = 0
162- limit = 100 # Default page size
171+ limit = batch_size # Default page size
163172
164173 while True :
165174 response = self ._fetch_page_as_response (limit = limit , offset = offset )
166- items_collection : Collection [ResourceType ] = Collection .from_response (response )
175+ items_collection : Collection [ResourceModel ] = self ._collection_class .from_response (
176+ response
177+ )
167178 yield from items_collection
168179
169180 if not items_collection .meta :
@@ -172,7 +183,11 @@ def iterate(self) -> Iterator[ResourceType]:
172183 break
173184 offset = items_collection .meta .pagination .next_offset ()
174185
175- def create (self , resource_data : dict [str , Any ]) -> ResourceType :
186+ def get (self , resource_id : str ) -> ResourceClient :
187+ """Get resource by resource_id."""
188+ return self ._resource_client_class (client = self .mpt_client , resource_id = resource_id )
189+
190+ def create (self , resource_data : dict [str , Any ]) -> ResourceModel :
176191 """Create a new resource using `POST /endpoint`.
177192
178193 Returns:
0 commit comments