Skip to content

Commit b177d20

Browse files
committed
MPT-13321 Add catalog products documents
1 parent f34a2d9 commit b177d20

5 files changed

Lines changed: 356 additions & 0 deletions

File tree

mpt_api_client/resources/catalog/products.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
AsyncPublishableMixin,
1212
PublishableMixin,
1313
)
14+
from mpt_api_client.resources.catalog.products_documents import (
15+
AsyncDocumentService,
16+
DocumentService,
17+
)
1418
from mpt_api_client.resources.catalog.products_item_groups import (
1519
AsyncItemGroupsService,
1620
ItemGroupsService,
@@ -69,6 +73,12 @@ def media(self, product_id: str) -> MediaService:
6973
http_client=self.http_client, endpoint_params={"product_id": product_id}
7074
)
7175

76+
def documents(self, product_id: str) -> DocumentService:
77+
"""Return documents service."""
78+
return DocumentService(
79+
http_client=self.http_client, endpoint_params={"product_id": product_id}
80+
)
81+
7282
def product_parameters(self, product_id: str) -> ParametersService:
7383
"""Return product_parameters service."""
7484
return ParametersService(
@@ -104,6 +114,12 @@ def media(self, product_id: str) -> AsyncMediaService:
104114
http_client=self.http_client, endpoint_params={"product_id": product_id}
105115
)
106116

117+
def documents(self, product_id: str) -> AsyncDocumentService:
118+
"""Return documents service."""
119+
return AsyncDocumentService(
120+
http_client=self.http_client, endpoint_params={"product_id": product_id}
121+
)
122+
107123
def product_parameters(self, product_id: str) -> AsyncParametersService:
108124
"""Return product_parameters service."""
109125
return AsyncParametersService(
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import json
2+
from typing import override
3+
4+
from httpx import Response
5+
from httpx._types import FileTypes
6+
7+
from mpt_api_client.http import AsyncService, CreateMixin, DeleteMixin, Service
8+
from mpt_api_client.http.mixins import (
9+
AsyncCreateMixin,
10+
AsyncDeleteMixin,
11+
AsyncUpdateMixin,
12+
UpdateMixin,
13+
)
14+
from mpt_api_client.models import FileModel, Model, ResourceData
15+
from mpt_api_client.resources.catalog.mixins import AsyncPublishableMixin, PublishableMixin
16+
17+
18+
def _json_to_file_payload(resource_data: ResourceData) -> bytes:
19+
return json.dumps(
20+
resource_data, ensure_ascii=False, separators=(",", ":"), allow_nan=False
21+
).encode("utf-8")
22+
23+
24+
class Document(Model):
25+
"""Document resource."""
26+
27+
28+
class DocumentServiceConfig:
29+
"""Document service configuration."""
30+
31+
_endpoint = "/public/v1/catalog/products/{product_id}/documents"
32+
_model_class = Document
33+
_collection_key = "data"
34+
35+
36+
class DocumentService(
37+
CreateMixin[Document],
38+
DeleteMixin,
39+
UpdateMixin[Document],
40+
PublishableMixin[Document],
41+
Service[Document],
42+
DocumentServiceConfig,
43+
):
44+
"""Document service."""
45+
46+
@override
47+
def create(
48+
self,
49+
resource_data: ResourceData | None = None,
50+
files: dict[str, FileTypes] | None = None, # noqa: WPS221
51+
) -> Document:
52+
"""Create Document resource.
53+
54+
Include the document as a file or add an url in resource_data to be uploaded.
55+
56+
Args:
57+
resource_data: Resource data.
58+
files: Files data.
59+
60+
Returns:
61+
Document resource.
62+
"""
63+
files = files or {}
64+
65+
if resource_data:
66+
files["_attachment_data"] = (
67+
None,
68+
_json_to_file_payload(resource_data),
69+
"application/json",
70+
)
71+
72+
response = self.http_client.post(self.endpoint, files=files)
73+
response.raise_for_status()
74+
return Document.from_response(response)
75+
76+
def download(self, document_id: str) -> FileModel:
77+
"""Download the document file for the given document ID.
78+
79+
Args:
80+
document_id: Document ID.
81+
82+
Returns:
83+
Document file.
84+
"""
85+
response: Response = self._resource_do_request(
86+
document_id, method="GET", headers={"Accept": "*"}
87+
)
88+
return FileModel(response)
89+
90+
91+
class AsyncDocumentService(
92+
AsyncCreateMixin[Document],
93+
AsyncDeleteMixin,
94+
AsyncUpdateMixin[Document],
95+
AsyncPublishableMixin[Document],
96+
AsyncService[Document],
97+
DocumentServiceConfig,
98+
):
99+
"""Document service."""
100+
101+
@override
102+
async def create(
103+
self,
104+
resource_data: ResourceData | None = None,
105+
files: dict[str, FileTypes] | None = None, # noqa: WPS221
106+
) -> Document:
107+
"""Create Document resource.
108+
109+
Include the document as a file or add an url in resource_data to be uploaded.
110+
111+
Args:
112+
resource_data: Resource data.
113+
files: Files data.
114+
115+
Returns:
116+
Document resource.
117+
"""
118+
files = files or {}
119+
120+
if resource_data:
121+
files["_attachment_data"] = (
122+
None,
123+
_json_to_file_payload(resource_data),
124+
"application/json",
125+
)
126+
127+
response = await self.http_client.post(self.endpoint, files=files)
128+
response.raise_for_status()
129+
return Document.from_response(response)
130+
131+
async def download(self, document_id: str) -> FileModel:
132+
"""Download the document file for the given document ID.
133+
134+
Args:
135+
document_id: Document ID.
136+
137+
Returns:
138+
Document file.
139+
"""
140+
response = await self._resource_do_request(
141+
document_id, method="GET", headers={"Accept": "*"}
142+
)
143+
return FileModel(response)

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ per-file-ignores =
3939
mpt_api_client/resources/catalog/products_parameter_groups.py: WPS215
4040
mpt_api_client/resources/catalog/products_parameters.py: WPS215
4141
mpt_api_client/resources/catalog/products_media.py: WPS215
42+
mpt_api_client/resources/catalog/products_documents.py: WPS215
4243
tests/http/test_async_service.py: WPS204 WPS202
4344
tests/http/test_service.py: WPS204 WPS202
4445

tests/resources/catalog/test_products.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import pytest
22

33
from mpt_api_client.resources.catalog.products import AsyncProductsService, ProductsService
4+
from mpt_api_client.resources.catalog.products_documents import (
5+
AsyncDocumentService,
6+
DocumentService,
7+
)
48
from mpt_api_client.resources.catalog.products_item_groups import (
59
AsyncItemGroupsService,
610
ItemGroupsService,
@@ -49,6 +53,7 @@ def test_async_mixins_present(async_products_service, method):
4953
("item_groups", ItemGroupsService),
5054
("parameter_groups", ParameterGroupsService),
5155
("media", MediaService),
56+
("documents", DocumentService),
5257
("product_parameters", ParametersService),
5358
],
5459
)
@@ -65,6 +70,7 @@ def test_property_services(products_service, service_method, expected_service_cl
6570
("item_groups", AsyncItemGroupsService),
6671
("parameter_groups", AsyncParameterGroupsService),
6772
("media", AsyncMediaService),
73+
("documents", AsyncDocumentService),
6874
("product_parameters", AsyncParametersService),
6975
],
7076
)

0 commit comments

Comments
 (0)