Skip to content

Commit 402e723

Browse files
committed
Fix service and improve orders docstrings
1 parent 35deded commit 402e723

File tree

7 files changed

+132
-21
lines changed

7 files changed

+132
-21
lines changed

mpt_api_client/http/async_service.py

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from mpt_api_client.http.async_client import AsyncHTTPClient
77
from mpt_api_client.http.base_service import ServiceBase
8+
from mpt_api_client.http.helper import prepare_query_params
9+
from mpt_api_client.http.types import QueryParam
810
from mpt_api_client.models import Collection, ResourceData
911
from mpt_api_client.models import Model as BaseModel
1012
from mpt_api_client.models.collection import ResourceList
@@ -23,7 +25,11 @@ class AsyncService[Model: BaseModel](ServiceBase[AsyncHTTPClient, Model]): # no
2325
"""
2426

2527
async def fetch_page(self, limit: int = 100, offset: int = 0) -> Collection[Model]:
26-
"""Fetch one page of resources."""
28+
"""Fetch one page of resources.
29+
30+
Returns:
31+
Collection of resources.
32+
"""
2733
response = await self._fetch_page_as_response(limit=limit, offset=offset)
2834
return self._create_collection(response)
2935

@@ -83,16 +89,39 @@ async def create(self, resource_data: ResourceData) -> Model:
8389

8490
return self._model_class.from_response(response)
8591

86-
async def get(self, resource_id: str) -> Model:
87-
"""Fetch a specific resource using `GET /endpoint/{resource_id}`."""
88-
return await self._resource_action(resource_id=resource_id)
92+
async def get(self, resource_id: str, select: list[str] | str | None = None) -> Model:
93+
"""Fetch a specific resource using `GET /endpoint/{resource_id}`.
94+
95+
Args:
96+
resource_id: Resource ID.
97+
select: List of fields to select.
98+
99+
Returns:
100+
Resource object.
101+
"""
102+
if isinstance(select, list):
103+
select = ",".join(select) if select else None
104+
return await self._resource_action(resource_id=resource_id, query_params={"select": select})
89105

90106
async def update(self, resource_id: str, resource_data: ResourceData) -> Model:
91-
"""Update a resource using `PUT /endpoint/{resource_id}`."""
107+
"""Update a resource using `PUT /endpoint/{resource_id}`.
108+
109+
Args:
110+
resource_id: Resource ID.
111+
resource_data: Resource data.
112+
113+
Returns:
114+
Resource object.
115+
116+
"""
92117
return await self._resource_action(resource_id, "PUT", json=resource_data)
93118

94119
async def delete(self, resource_id: str) -> None:
95-
"""Delete resource using `DELETE /endpoint/{resource_id}`."""
120+
"""Delete resource using `DELETE /endpoint/{resource_id}`.
121+
122+
Args:
123+
resource_id: Resource ID.
124+
"""
96125
url = urljoin(f"{self._endpoint}/", resource_id)
97126
response = await self.http_client.delete(url)
98127
response.raise_for_status()
@@ -118,6 +147,7 @@ async def _resource_do_request(
118147
method: str = "GET",
119148
action: str | None = None,
120149
json: ResourceData | ResourceList | None = None,
150+
query_params: QueryParam | None = None,
121151
) -> httpx.Response:
122152
"""Perform an action on a specific resource using.
123153
@@ -129,13 +159,16 @@ async def _resource_do_request(
129159
method: The HTTP method to use.
130160
action: The action name to use.
131161
json: The updated resource data.
162+
query_params: Additional query parameters.
132163
133164
Raises:
134165
HTTPError: If the action fails.
135166
"""
136167
resource_url = urljoin(f"{self._endpoint}/", resource_id)
137168
url = urljoin(f"{resource_url}/", action) if action else resource_url
138-
response = await self.http_client.request(method, url, json=json)
169+
response = await self.http_client.request(
170+
method, url, json=json, params=prepare_query_params(query_params)
171+
)
139172
response.raise_for_status()
140173
return response
141174

@@ -145,7 +178,18 @@ async def _resource_action(
145178
method: str = "GET",
146179
action: str | None = None,
147180
json: ResourceData | ResourceList | None = None,
181+
query_params: QueryParam | None = None,
148182
) -> Model:
149-
"""Perform an action on a specific resource using `HTTP_METHOD /endpoint/{resource_id}`."""
150-
response = await self._resource_do_request(resource_id, method, action, json=json)
183+
"""Perform an action on a specific resource using `HTTP_METHOD /endpoint/{resource_id}`.
184+
185+
Args:
186+
resource_id: The resource ID to operate on.
187+
method: The HTTP method to use.
188+
action: The action name to use.
189+
json: The updated resource data.
190+
query_params: Additional query parameters.
191+
"""
192+
response = await self._resource_do_request(
193+
resource_id, method, action, json=json, query_params=query_params
194+
)
151195
return self._model_class.from_response(response)

mpt_api_client/http/helper.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from mpt_api_client.http.types import QueryParam
2+
3+
4+
def prepare_query_params(query_params: QueryParam | None) -> dict[str, str] | None:
5+
"""
6+
Prepare and clean the query params dict.
7+
8+
Converts all params to string and removes any value that is None.
9+
10+
Args:
11+
query_params: dict of query params.
12+
13+
Returns:
14+
dict or None if the params were not present.
15+
16+
"""
17+
if not query_params:
18+
return None
19+
clean_params = {
20+
param_name: str(param_value)
21+
for param_name, param_value in query_params.items()
22+
if param_value is not None
23+
}
24+
return clean_params or None

mpt_api_client/http/service.py

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from mpt_api_client.http.base_service import ServiceBase
77
from mpt_api_client.http.client import HTTPClient
8+
from mpt_api_client.http.helper import prepare_query_params
9+
from mpt_api_client.http.types import QueryParam
810
from mpt_api_client.models import Collection, ResourceData
911
from mpt_api_client.models import Model as BaseModel
1012
from mpt_api_client.models.collection import ResourceList
@@ -86,16 +88,40 @@ def create(self, resource_data: ResourceData) -> Model:
8688

8789
return self._model_class.from_response(response)
8890

89-
def get(self, resource_id: str) -> Model:
90-
"""Fetch a specific resource using `GET /endpoint/{resource_id}`."""
91-
return self._resource_action(resource_id=resource_id)
91+
def get(self, resource_id: str, select: list[str] | str | None = None) -> Model:
92+
"""Fetch a specific resource using `GET /endpoint/{resource_id}`.
93+
94+
Args:
95+
resource_id: Resource ID.
96+
select: List of fields to select.
97+
98+
Returns:
99+
Resource object.
100+
"""
101+
if isinstance(select, list):
102+
select = ",".join(select) if select else None
103+
104+
return self._resource_action(resource_id=resource_id, query_params={"select": select})
92105

93106
def update(self, resource_id: str, resource_data: ResourceData) -> Model:
94-
"""Update a resource using `PUT /endpoint/{resource_id}`."""
107+
"""Update a resource using `PUT /endpoint/{resource_id}`.
108+
109+
Args:
110+
resource_id: Resource ID.
111+
resource_data: Resource data.
112+
113+
Returns:
114+
Resource object.
115+
116+
"""
95117
return self._resource_action(resource_id, "PUT", json=resource_data)
96118

97119
def delete(self, resource_id: str) -> None:
98-
"""Delete the resoruce using `DELETE /endpoint/{resource_id}`."""
120+
"""Delete resource using `DELETE /endpoint/{resource_id}`.
121+
122+
Args:
123+
resource_id: Resource ID.
124+
"""
99125
response = self._resource_do_request(resource_id, "DELETE")
100126
response.raise_for_status()
101127

@@ -120,6 +146,7 @@ def _resource_do_request(
120146
method: str = "GET",
121147
action: str | None = None,
122148
json: ResourceData | ResourceList | None = None,
149+
query_params: QueryParam | None = None,
123150
) -> httpx.Response:
124151
"""Perform an action on a specific resource using `HTTP_METHOD /endpoint/{resource_id}`.
125152
@@ -128,6 +155,7 @@ def _resource_do_request(
128155
method: The HTTP method to use.
129156
action: The action name to use.
130157
json: The updated resource data.
158+
query_params: Additional query parameters.
131159
132160
Returns:
133161
HTTP response object.
@@ -137,7 +165,9 @@ def _resource_do_request(
137165
"""
138166
resource_url = urljoin(f"{self._endpoint}/", resource_id)
139167
url = urljoin(f"{resource_url}/", action) if action else resource_url
140-
response = self.http_client.request(method, url, json=json)
168+
response = self.http_client.request(
169+
method, url, json=json, params=prepare_query_params(query_params)
170+
)
141171
response.raise_for_status()
142172
return response
143173

@@ -147,7 +177,18 @@ def _resource_action(
147177
method: str = "GET",
148178
action: str | None = None,
149179
json: ResourceData | ResourceList | None = None,
180+
query_params: QueryParam | None = None,
150181
) -> Model:
151-
"""Perform an action on a specific resource using `HTTP_METHOD /endpoint/{resource_id}`."""
152-
response = self._resource_do_request(resource_id, method, action, json=json)
182+
"""Perform an action on a specific resource using `HTTP_METHOD /endpoint/{resource_id}`.
183+
184+
Args:
185+
resource_id: The resource ID to operate on.
186+
method: The HTTP method to use.
187+
action: The action name to use.
188+
json: The updated resource data.
189+
query_params: Additional query parameters.
190+
"""
191+
response = self._resource_do_request(
192+
resource_id, method, action, json=json, query_params=query_params
193+
)
153194
return self._model_class.from_response(response)

mpt_api_client/http/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
PrimitiveType = str | int | float | bool | None
2+
QueryParam = dict[str, PrimitiveType]

mpt_api_client/resources/commerce/orders.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class OrdersServiceConfig:
1515

1616

1717
class OrdersService(Service[Order], OrdersServiceConfig):
18-
"""Orders client."""
18+
"""Orders service."""
1919

2020
def validate(self, resource_id: str, resource_data: ResourceData | None = None) -> Order:
2121
"""Switch order to validate state.
@@ -85,7 +85,7 @@ def template(self, resource_id: str) -> str:
8585

8686

8787
class AsyncOrdersService(AsyncService[Order], OrdersServiceConfig):
88-
"""Async Orders client."""
88+
"""Async Orders service."""
8989

9090
async def validate(self, resource_id: str, resource_data: ResourceData | None = None) -> Order:
9191
"""Switch order to validate state.

tests/http/test_async_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,6 @@ async def test_async_get(async_dummy_service):
300300
return_value=httpx.Response(httpx.codes.OK, json=resource_data)
301301
)
302302

303-
resource = await async_dummy_service.get("RES-123")
303+
resource = await async_dummy_service.get("RES-123", select=["id", "name"])
304304
assert isinstance(resource, DummyModel)
305305
assert resource.to_dict() == resource_data

tests/http/test_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def test_sync_get(dummy_service):
101101
return_value=httpx.Response(httpx.codes.OK, json=resource_data)
102102
)
103103

104-
resource = dummy_service.get("RES-123")
104+
resource = dummy_service.get("RES-123", select=["id", "name"])
105105
assert isinstance(resource, DummyModel)
106106
assert resource.to_dict() == resource_data
107107

0 commit comments

Comments
 (0)