11import json
2+ from typing import Self
23from urllib .parse import urljoin
34
5+ from mpt_api_client .http .query_state import QueryState
46from mpt_api_client .http .types import FileTypes , Response
57from mpt_api_client .models import FileModel , ResourceData
8+ from mpt_api_client .rql import RQLQuery
69
710
811def _json_to_file_payload (resource_data : ResourceData ) -> bytes :
@@ -20,7 +23,7 @@ def create(self, resource_data: ResourceData) -> Model:
2023 Returns:
2124 New resource created.
2225 """
23- response = self .http_client .request ("post" , self .endpoint , json = resource_data ) # type: ignore[attr-defined]
26+ response = self .http_client .request ("post" , self .path , json = resource_data ) # type: ignore[attr-defined]
2427
2528 return self ._model_class .from_response (response ) # type: ignore[attr-defined, no-any-return]
2629
@@ -82,7 +85,7 @@ def create(
8285 "application/json" ,
8386 )
8487
85- response = self .http_client .request ("post" , self .endpoint , files = files ) # type: ignore[attr-defined]
88+ response = self .http_client .request ("post" , self .path , files = files ) # type: ignore[attr-defined]
8689
8790 return self ._model_class .from_response (response ) # type: ignore[attr-defined, no-any-return]
8891
@@ -110,7 +113,7 @@ async def create(self, resource_data: ResourceData) -> Model:
110113 Returns:
111114 New resource created.
112115 """
113- response = await self .http_client .request ("post" , self .endpoint , json = resource_data ) # type: ignore[attr-defined]
116+ response = await self .http_client .request ("post" , self .path , json = resource_data ) # type: ignore[attr-defined]
114117
115118 return self ._model_class .from_response (response ) # type: ignore[attr-defined, no-any-return]
116119
@@ -124,7 +127,7 @@ async def delete(self, resource_id: str) -> None:
124127 Args:
125128 resource_id: Resource ID.
126129 """
127- url = urljoin (f"{ self .endpoint } /" , resource_id ) # type: ignore[attr-defined]
130+ url = urljoin (f"{ self .path } /" , resource_id ) # type: ignore[attr-defined]
128131 await self .http_client .request ("delete" , url ) # type: ignore[attr-defined]
129132
130133
@@ -173,7 +176,7 @@ async def create(
173176 "application/json" ,
174177 )
175178
176- response = await self .http_client .request ("post" , self .endpoint , files = files ) # type: ignore[attr-defined]
179+ response = await self .http_client .request ("post" , self .path , files = files ) # type: ignore[attr-defined]
177180
178181 return self ._model_class .from_response (response ) # type: ignore[attr-defined, no-any-return]
179182
@@ -227,3 +230,74 @@ async def get(self, resource_id: str, select: list[str] | str | None = None) ->
227230 if isinstance (select , list ):
228231 select = "," .join (select ) if select else None
229232 return await self ._resource_action (resource_id = resource_id , query_params = {"select" : select }) # type: ignore[attr-defined, no-any-return]
233+
234+
235+ class QueryableMixin :
236+ """Mixin providing query functionality for filtering, ordering, and selecting fields."""
237+
238+ def order_by (self , * fields : str ) -> Self :
239+ """Returns new collection with ordering setup.
240+
241+ Returns:
242+ New collection with ordering setup.
243+
244+ Raises:
245+ ValueError: If ordering has already been set.
246+ """
247+ if self .query_state .order_by is not None : # type: ignore[attr-defined]
248+ raise ValueError ("Ordering is already set. Cannot set ordering multiple times." )
249+ return self ._create_new_instance (
250+ query_state = QueryState (
251+ rql = self .query_state .filter , # type: ignore[attr-defined]
252+ order_by = list (fields ),
253+ select = self .query_state .select , # type: ignore[attr-defined]
254+ )
255+ )
256+
257+ def filter (self , rql : RQLQuery ) -> Self :
258+ """Creates a new collection with the filter added to the filter collection.
259+
260+ Returns:
261+ New copy of the collection with the filter added.
262+ """
263+ existing_filter = self .query_state .filter # type: ignore[attr-defined]
264+ combined_filter = existing_filter & rql if existing_filter else rql
265+ return self ._create_new_instance (
266+ QueryState (
267+ rql = combined_filter ,
268+ order_by = self .query_state .order_by , # type: ignore[attr-defined]
269+ select = self .query_state .select , # type: ignore[attr-defined]
270+ )
271+ )
272+
273+ def select (self , * fields : str ) -> Self :
274+ """Set select fields. Raises ValueError if select fields are already set.
275+
276+ Returns:
277+ New copy of the collection with the select fields set.
278+
279+ Raises:
280+ ValueError: If select fields are already set.
281+ """
282+ if self .query_state .select is not None : # type: ignore[attr-defined]
283+ raise ValueError (
284+ "Select fields are already set. Cannot set select fields multiple times."
285+ )
286+ return self ._create_new_instance (
287+ QueryState (
288+ rql = self .query_state .filter , # type: ignore[attr-defined]
289+ order_by = self .query_state .order_by , # type: ignore[attr-defined]
290+ select = list (fields ),
291+ ),
292+ )
293+
294+ def _create_new_instance (
295+ self ,
296+ query_state : QueryState ,
297+ ) -> Self :
298+ """Create a new instance with the given parameters."""
299+ return self .__class__ (
300+ http_client = self .http_client , # type: ignore[call-arg,attr-defined]
301+ query_state = query_state ,
302+ endpoint_params = self .endpoint_params , # type: ignore[attr-defined]
303+ )
0 commit comments