Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions mpt_api_client/resources/catalog/product_terms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from mpt_api_client.http import AsyncService, CreateMixin, DeleteMixin, Service
from mpt_api_client.http.mixins import (
AsyncCreateMixin,
AsyncDeleteMixin,
AsyncUpdateMixin,
UpdateMixin,
)
from mpt_api_client.models import Model
from mpt_api_client.resources.catalog.mixins import AsyncPublishableMixin, PublishableMixin


class Term(Model):
"""Term resource."""


class TermServiceConfig:
"""Term service configuration."""

_endpoint = "/public/v1/catalog/products/{product_id}/terms"
_model_class = Term
_collection_key = "data"


class TermService(
CreateMixin[Term],
DeleteMixin,
UpdateMixin[Term],
PublishableMixin[Term],
Service[Term],
TermServiceConfig,
):
"""Term service."""


class AsyncTermService(
AsyncCreateMixin[Term],
AsyncDeleteMixin,
AsyncUpdateMixin[Term],
AsyncPublishableMixin[Term],
AsyncService[Term],
TermServiceConfig,
):
"""Async Term service."""
46 changes: 46 additions & 0 deletions mpt_api_client/resources/catalog/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
AsyncPublishableMixin,
PublishableMixin,
)
from mpt_api_client.resources.catalog.product_terms import (
AsyncTermService,
TermService,
)
from mpt_api_client.resources.catalog.products_documents import (
AsyncDocumentService,
DocumentService,
)
from mpt_api_client.resources.catalog.products_item_groups import (
AsyncItemGroupsService,
ItemGroupsService,
Expand All @@ -27,6 +35,10 @@
AsyncParametersService,
ParametersService,
)
from mpt_api_client.resources.catalog.products_templates import (
AsyncTemplatesService,
TemplatesService,
)


class Product(Model):
Expand Down Expand Up @@ -69,12 +81,28 @@ def media(self, product_id: str) -> MediaService:
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def documents(self, product_id: str) -> DocumentService:
"""Return documents service."""
return DocumentService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def product_parameters(self, product_id: str) -> ParametersService:
"""Return product_parameters service."""
return ParametersService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def templates(self, product_id: str) -> TemplatesService:
"""Return templates service."""
return TemplatesService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def terms(self, product_id: str) -> TermService:
"""Return terms service."""
return TermService(http_client=self.http_client, endpoint_params={"product_id": product_id})


class AsyncProductsService(
AsyncCreateMixin[Product],
Expand Down Expand Up @@ -104,8 +132,26 @@ def media(self, product_id: str) -> AsyncMediaService:
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def documents(self, product_id: str) -> AsyncDocumentService:
"""Return documents service."""
return AsyncDocumentService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def product_parameters(self, product_id: str) -> AsyncParametersService:
"""Return product_parameters service."""
return AsyncParametersService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def templates(self, product_id: str) -> AsyncTemplatesService:
"""Return templates service."""
return AsyncTemplatesService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)

def terms(self, product_id: str) -> AsyncTermService:
"""Return terms service."""
return AsyncTermService(
http_client=self.http_client, endpoint_params={"product_id": product_id}
)
143 changes: 143 additions & 0 deletions mpt_api_client/resources/catalog/products_documents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import json
from typing import override

from httpx import Response
from httpx._types import FileTypes

from mpt_api_client.http import AsyncService, CreateMixin, DeleteMixin, Service
from mpt_api_client.http.mixins import (
AsyncCreateMixin,
AsyncDeleteMixin,
AsyncUpdateMixin,
UpdateMixin,
)
from mpt_api_client.models import FileModel, Model, ResourceData
from mpt_api_client.resources.catalog.mixins import AsyncPublishableMixin, PublishableMixin


def _json_to_file_payload(resource_data: ResourceData) -> bytes:
return json.dumps(
resource_data, ensure_ascii=False, separators=(",", ":"), allow_nan=False
).encode("utf-8")


class Document(Model):
"""Document resource."""


class DocumentServiceConfig:
"""Document service configuration."""

_endpoint = "/public/v1/catalog/products/{product_id}/documents"
_model_class = Document
_collection_key = "data"


class DocumentService(
CreateMixin[Document],
DeleteMixin,
UpdateMixin[Document],
PublishableMixin[Document],
Service[Document],
DocumentServiceConfig,
):
"""Document service."""

@override
def create(
self,
resource_data: ResourceData | None = None,
files: dict[str, FileTypes] | None = None, # noqa: WPS221
) -> Document:
"""Create Document resource.

Include the document as a file or add an url in resource_data to be uploaded.

Args:
resource_data: Resource data.
files: Files data.

Returns:
Document resource.
"""
files = files or {}

if resource_data:
files["_attachment_data"] = (
None,
_json_to_file_payload(resource_data),
"application/json",
)

response = self.http_client.post(self.endpoint, files=files)
response.raise_for_status()
return Document.from_response(response)

def download(self, document_id: str) -> FileModel:
"""Download the document file for the given document ID.

Args:
document_id: Document ID.

Returns:
Document file.
"""
response: Response = self._resource_do_request(
document_id, method="GET", headers={"Accept": "*"}
)
return FileModel(response)


class AsyncDocumentService(
AsyncCreateMixin[Document],
AsyncDeleteMixin,
AsyncUpdateMixin[Document],
AsyncPublishableMixin[Document],
AsyncService[Document],
DocumentServiceConfig,
):
"""Document service."""

@override
async def create(
self,
resource_data: ResourceData | None = None,
files: dict[str, FileTypes] | None = None, # noqa: WPS221
) -> Document:
"""Create Document resource.

Include the document as a file or add an url in resource_data to be uploaded.

Args:
resource_data: Resource data.
files: Files data.

Returns:
Document resource.
"""
files = files or {}

if resource_data:
files["_attachment_data"] = (
None,
_json_to_file_payload(resource_data),
"application/json",
)

response = await self.http_client.post(self.endpoint, files=files)
response.raise_for_status()
return Document.from_response(response)

async def download(self, document_id: str) -> FileModel:
"""Download the document file for the given document ID.

Args:
document_id: Document ID.

Returns:
Document file.
"""
response = await self._resource_do_request(
document_id, method="GET", headers={"Accept": "*"}
)
return FileModel(response)
40 changes: 40 additions & 0 deletions mpt_api_client/resources/catalog/products_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from mpt_api_client.http import AsyncService, CreateMixin, DeleteMixin, Service
from mpt_api_client.http.mixins import (
AsyncCreateMixin,
AsyncDeleteMixin,
AsyncUpdateMixin,
UpdateMixin,
)
from mpt_api_client.models import Model


class Template(Model):
"""Template resource."""


class TemplatesServiceConfig:
"""Templates service configuration."""

_endpoint = "/public/v1/catalog/products/{product_id}/templates"
_model_class = Template
_collection_key = "data"


class TemplatesService(
CreateMixin[Template],
DeleteMixin,
UpdateMixin[Template],
Service[Template],
TemplatesServiceConfig,
):
"""Templates service."""


class AsyncTemplatesService(
AsyncCreateMixin[Template],
AsyncDeleteMixin,
AsyncUpdateMixin[Template],
AsyncService[Template],
TemplatesServiceConfig,
):
"""Templates service."""
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ per-file-ignores =
mpt_api_client/resources/catalog/products_parameter_groups.py: WPS215
mpt_api_client/resources/catalog/products_parameters.py: WPS215
mpt_api_client/resources/catalog/products_media.py: WPS215
mpt_api_client/resources/catalog/products_documents.py: WPS215
mpt_api_client/resources/catalog/products_templates.py: WPS215
mpt_api_client/resources/catalog/product_terms.py: WPS215
tests/http/test_async_service.py: WPS204 WPS202
tests/http/test_service.py: WPS204 WPS202

Expand Down
40 changes: 40 additions & 0 deletions tests/resources/catalog/test_product_terms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import pytest

from mpt_api_client.resources.catalog.product_terms import (
AsyncTermService,
TermService,
)


@pytest.fixture
def term_service(http_client):
return TermService(http_client=http_client, endpoint_params={"product_id": "PRD-001"})


@pytest.fixture
def async_term_service(async_http_client):
return AsyncTermService(
http_client=async_http_client, endpoint_params={"product_id": "PRD-001"}
)


def test_endpoint(term_service):
assert term_service.endpoint == "/public/v1/catalog/products/PRD-001/terms"


def test_async_endpoint(async_term_service):
assert async_term_service.endpoint == "/public/v1/catalog/products/PRD-001/terms"


@pytest.mark.parametrize(
"method", ["get", "create", "delete", "update", "review", "publish", "unpublish"]
)
def test_methods_present(term_service, method):
assert hasattr(term_service, method)


@pytest.mark.parametrize(
"method", ["get", "create", "delete", "update", "review", "publish", "unpublish"]
)
def test_async_methods_present(async_term_service, method):
assert hasattr(async_term_service, method)
Loading