From 29715be9871ed9fe8854f2a8df0c5b8f80f3d87f Mon Sep 17 00:00:00 2001 From: Nathan Fallet Date: Sat, 24 Oct 2026 02:13:19 +0100 Subject: [PATCH 1/4] feat: regenerate with the catalog and webhook routes and expose them The client is regenerated from the OpenAPI document of the API with every route, the catalog and the webhooks included. client.catalogs reads the identifiers an item is written with; client.webhooks manages the endpoints, their secrets and deliveries, and reads the events of the last 7 days. --- .spec-sha256 | 2 +- README.md | 11 + src/controlresell/client.py | 292 ++++++++++++++++++ .../generated/api/catalogs/__init__.py | 1 + .../api/catalogs/get_catalog_category.py | 197 ++++++++++++ .../catalogs/get_catalog_category_fields.py | 217 +++++++++++++ .../api/catalogs/list_catalog_brands.py | 235 ++++++++++++++ .../api/catalogs/list_catalog_categories.py | 259 ++++++++++++++++ .../api/catalogs/list_catalog_colors.py | 236 ++++++++++++++ .../api/catalogs/list_catalog_conditions.py | 236 ++++++++++++++ .../api/catalogs/list_catalog_materials.py | 236 ++++++++++++++ .../catalogs/list_catalog_package_sizes.py | 236 ++++++++++++++ .../api/catalogs/list_catalog_sizes.py | 236 ++++++++++++++ .../generated/api/webhooks/__init__.py | 1 + .../api/webhooks/create_webhook_endpoint.py | 242 +++++++++++++++ .../api/webhooks/delete_webhook_endpoint.py | 200 ++++++++++++ .../api/webhooks/get_webhook_endpoint.py | 197 ++++++++++++ .../api/webhooks/get_webhook_secret.py | 206 ++++++++++++ .../api/webhooks/list_webhook_deliveries.py | 272 ++++++++++++++++ .../api/webhooks/list_webhook_endpoints.py | 168 ++++++++++ .../api/webhooks/list_webhook_event_types.py | 154 +++++++++ .../api/webhooks/list_webhook_events.py | 254 +++++++++++++++ .../webhooks/recover_webhook_deliveries.py | 251 +++++++++++++++ .../api/webhooks/retry_webhook_delivery.py | 255 +++++++++++++++ .../api/webhooks/rotate_webhook_secret.py | 256 +++++++++++++++ .../api/webhooks/test_webhook_endpoint.py | 206 ++++++++++++ .../api/webhooks/update_webhook_endpoint.py | 231 ++++++++++++++ .../generated/models/__init__.py | 58 ++++ .../generated/models/catalog_brand.py | 77 +++++ .../generated/models/catalog_brand_page.py | 97 ++++++ .../generated/models/catalog_category.py | 115 +++++++ .../models/catalog_category_fields.py | 127 ++++++++ .../generated/models/catalog_category_page.py | 97 ++++++ .../generated/models/catalog_enum_field.py | 153 +++++++++ .../generated/models/catalog_measurement.py | 77 +++++ .../generated/models/catalog_size.py | 85 +++++ .../generated/models/catalog_size_page.py | 97 ++++++ .../generated/models/catalog_text_field.py | 139 +++++++++ .../generated/models/catalog_value.py | 77 +++++ .../generated/models/catalog_value_page.py | 97 ++++++ .../models/created_webhook_endpoint.py | 75 +++++ .../generated/models/webhook_delivery.py | 203 ++++++++++++ .../generated/models/webhook_delivery_page.py | 97 ++++++ .../generated/models/webhook_endpoint.py | 191 ++++++++++++ .../models/webhook_endpoint_create_request.py | 111 +++++++ .../generated/models/webhook_endpoint_page.py | 97 ++++++ .../models/webhook_endpoint_update_request.py | 164 ++++++++++ .../generated/models/webhook_event.py | 109 +++++++ .../generated/models/webhook_event_data.py | 45 +++ .../generated/models/webhook_event_page.py | 97 ++++++ .../generated/models/webhook_event_type.py | 83 +++++ .../models/webhook_event_type_list.py | 75 +++++ .../models/webhook_recover_request.py | 62 ++++ .../generated/models/webhook_recovery.py | 69 +++++ .../generated/models/webhook_secret.py | 100 ++++++ .../models/webhook_secret_rotate_request.py | 73 +++++ .../generated/models/webhook_test_result.py | 111 +++++++ tests/test_client.py | 103 ++++++ 58 files changed, 8447 insertions(+), 1 deletion(-) create mode 100644 src/controlresell/generated/api/catalogs/__init__.py create mode 100644 src/controlresell/generated/api/catalogs/get_catalog_category.py create mode 100644 src/controlresell/generated/api/catalogs/get_catalog_category_fields.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_brands.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_categories.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_colors.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_conditions.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_materials.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_package_sizes.py create mode 100644 src/controlresell/generated/api/catalogs/list_catalog_sizes.py create mode 100644 src/controlresell/generated/api/webhooks/__init__.py create mode 100644 src/controlresell/generated/api/webhooks/create_webhook_endpoint.py create mode 100644 src/controlresell/generated/api/webhooks/delete_webhook_endpoint.py create mode 100644 src/controlresell/generated/api/webhooks/get_webhook_endpoint.py create mode 100644 src/controlresell/generated/api/webhooks/get_webhook_secret.py create mode 100644 src/controlresell/generated/api/webhooks/list_webhook_deliveries.py create mode 100644 src/controlresell/generated/api/webhooks/list_webhook_endpoints.py create mode 100644 src/controlresell/generated/api/webhooks/list_webhook_event_types.py create mode 100644 src/controlresell/generated/api/webhooks/list_webhook_events.py create mode 100644 src/controlresell/generated/api/webhooks/recover_webhook_deliveries.py create mode 100644 src/controlresell/generated/api/webhooks/retry_webhook_delivery.py create mode 100644 src/controlresell/generated/api/webhooks/rotate_webhook_secret.py create mode 100644 src/controlresell/generated/api/webhooks/test_webhook_endpoint.py create mode 100644 src/controlresell/generated/api/webhooks/update_webhook_endpoint.py create mode 100644 src/controlresell/generated/models/catalog_brand.py create mode 100644 src/controlresell/generated/models/catalog_brand_page.py create mode 100644 src/controlresell/generated/models/catalog_category.py create mode 100644 src/controlresell/generated/models/catalog_category_fields.py create mode 100644 src/controlresell/generated/models/catalog_category_page.py create mode 100644 src/controlresell/generated/models/catalog_enum_field.py create mode 100644 src/controlresell/generated/models/catalog_measurement.py create mode 100644 src/controlresell/generated/models/catalog_size.py create mode 100644 src/controlresell/generated/models/catalog_size_page.py create mode 100644 src/controlresell/generated/models/catalog_text_field.py create mode 100644 src/controlresell/generated/models/catalog_value.py create mode 100644 src/controlresell/generated/models/catalog_value_page.py create mode 100644 src/controlresell/generated/models/created_webhook_endpoint.py create mode 100644 src/controlresell/generated/models/webhook_delivery.py create mode 100644 src/controlresell/generated/models/webhook_delivery_page.py create mode 100644 src/controlresell/generated/models/webhook_endpoint.py create mode 100644 src/controlresell/generated/models/webhook_endpoint_create_request.py create mode 100644 src/controlresell/generated/models/webhook_endpoint_page.py create mode 100644 src/controlresell/generated/models/webhook_endpoint_update_request.py create mode 100644 src/controlresell/generated/models/webhook_event.py create mode 100644 src/controlresell/generated/models/webhook_event_data.py create mode 100644 src/controlresell/generated/models/webhook_event_page.py create mode 100644 src/controlresell/generated/models/webhook_event_type.py create mode 100644 src/controlresell/generated/models/webhook_event_type_list.py create mode 100644 src/controlresell/generated/models/webhook_recover_request.py create mode 100644 src/controlresell/generated/models/webhook_recovery.py create mode 100644 src/controlresell/generated/models/webhook_secret.py create mode 100644 src/controlresell/generated/models/webhook_secret_rotate_request.py create mode 100644 src/controlresell/generated/models/webhook_test_result.py diff --git a/.spec-sha256 b/.spec-sha256 index fa982ec..35c0bf5 100644 --- a/.spec-sha256 +++ b/.spec-sha256 @@ -1 +1 @@ -41311cb64247613fcc1634a63a1804e344c71873d665fc58af33e053a5f919f1 +f10e5e1224ad85ecad716478692839f8420090b5fa2f1dfcc9b0d287634172a3 diff --git a/README.md b/README.md index 6f4d88e..2230ba9 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ for item in client.items.iter(sold=False): print(item.name) for order in client.orders.iter(bucket="to_send"): # needs the orders:read scope; also orders.get(id), orders.labels(id) print(order.id) +for brand in client.catalogs.iter_brands(q="nik"): # the identifiers an item is written with (items:read): categories, category, category_fields, brands, sizes, colors, conditions, package_sizes, materials + print(brand.id, brand.name) # Writes (API key with `items:write` / `conversations:write`); `idempotency_key=` chooses the key. from controlresell.generated.models import ItemCreateRequest, ItemUpdateRequest, PublishRequest, SendMessageRequest @@ -19,6 +21,15 @@ client.items.create(ItemCreateRequest(name="Jacket")) # client.items.update(42, client.items.publish(42, PublishRequest(account_ids=[""])) client.conversations.send_message("", SendMessageRequest(text="Hello!")) + +# Webhooks (`webhooks:read` / `webhooks:write`): endpoints, endpoint, create_endpoint, update_endpoint, delete_endpoint, +# secret, rotate_secret, test, deliveries, retry_delivery, recover, event_types; iter_events catches up the last 7 days. +from controlresell.generated.models import WebhookEndpointCreateRequest + +created = client.webhooks.create_endpoint(WebhookEndpointCreateRequest(url="https://example.com/hooks", event_types=["item.sold"])) +print(created.endpoint.id, created.secret) # the signing secret, shown once (client.webhooks.secret(id) reads it again) +for event in client.webhooks.iter_events(types=["item.sold"]): + print(event.type_, event.data["itemId"]) ``` Retries (rate limits, 502/503/504, network errors), `Idempotency-Key` on every `POST`, cursor pagination with plain iterators and typed errors (`NotFoundError`, `RateLimitError`...) are built in. The client is generated from the API's OpenAPI document (`scripts/generate.sh`, code in `src/controlresell/generated`). diff --git a/src/controlresell/client.py b/src/controlresell/client.py index 7aeff5d..f7b644d 100644 --- a/src/controlresell/client.py +++ b/src/controlresell/client.py @@ -33,15 +33,51 @@ republish_item, update_item, ) +from .generated.api.catalogs import ( + get_catalog_category, + get_catalog_category_fields, + list_catalog_brands, + list_catalog_categories, + list_catalog_colors, + list_catalog_conditions, + list_catalog_materials, + list_catalog_package_sizes, + list_catalog_sizes, +) from .generated.api.customers import get_customer, list_customers +from .generated.api.webhooks import ( + create_webhook_endpoint, + delete_webhook_endpoint, + get_webhook_endpoint, + get_webhook_secret, + list_webhook_deliveries, + list_webhook_endpoints, + list_webhook_event_types, + list_webhook_events, + recover_webhook_deliveries, + retry_webhook_delivery, + rotate_webhook_secret, + test_webhook_endpoint, + update_webhook_endpoint, +) from .generated.api.me import get_me from .generated.api.orders import get_order, list_labels_to_ship, list_order_labels, list_orders from .generated.client import AuthenticatedClient from .generated.models import ( Account, AccountPage, + CatalogBrand, + CatalogBrandPage, + CatalogCategory, + CatalogCategoryFields, + CatalogCategoryPage, + CatalogSize, + CatalogSizePage, + CatalogValue, + CatalogValuePage, Conversation, ConversationPage, + CreatedWebhookEndpoint, Customer, CustomerPage, Item, @@ -62,6 +98,20 @@ ScheduledAction, SendMessageRequest, SendOfferRequest, + WebhookDelivery, + WebhookDeliveryPage, + WebhookEndpoint, + WebhookEndpointCreateRequest, + WebhookEndpointPage, + WebhookEndpointUpdateRequest, + WebhookEvent, + WebhookEventPage, + WebhookEventTypeList, + WebhookRecoverRequest, + WebhookRecovery, + WebhookSecret, + WebhookSecretRotateRequest, + WebhookTestResult, ) from .generated.types import UNSET from .pagination import paginate @@ -113,6 +163,8 @@ def __init__( self.conversations = _Conversations(self) self.orders = _Orders(self) self.customers = _Customers(self) + self.catalogs = _Catalogs(self) + self.webhooks = _Webhooks(self) @property def http(self) -> httpx.Client: @@ -430,3 +482,243 @@ def iter( ) -> Iterator[Customer]: """Every customer, page after page, with the same filters.""" return paginate(lambda cursor: self.list(limit=limit, cursor=cursor, account_id=account_id, from_=from_, to=to)) + + +class _Catalogs: + """The catalog an item is written with: categories, brands, sizes, colors... (needs the ``items:read`` scope). + + Every ``category_id`` keeps what applies to one category. + """ + + def __init__(self, sdk: ControlResell) -> None: + self._sdk = sdk + + def categories( + self, + *, + limit: int | None = None, + cursor: str | None = None, + parent_id: int | None = None, + platform: str | None = None, + ) -> CatalogCategoryPage: + """One page of categories, flat, by identifier; ``parent_id`` keeps the children of one, ``platform`` one marketplace.""" + return self._sdk._call( # noqa: SLF001 + list_catalog_categories, **_query(limit=limit, cursor=cursor, parent_id=parent_id, platform=platform) + ) + + def iter_categories( + self, *, limit: int | None = None, parent_id: int | None = None, platform: str | None = None + ) -> Iterator[CatalogCategory]: + """Every category, page after page, with the same filters.""" + return paginate( + lambda cursor: self.categories(limit=limit, cursor=cursor, parent_id=parent_id, platform=platform) + ) + + def category(self, id: int) -> CatalogCategory: + """One category by its identifier.""" + return self._sdk._call(get_catalog_category, id=id) # noqa: SLF001 + + def category_fields(self, id: int) -> CatalogCategoryFields: + """What an item of a category is filled with: its size groups, enumerated and text fields, measurements.""" + return self._sdk._call(get_catalog_category_fields, id=id) # noqa: SLF001 + + def brands(self, *, limit: int | None = None, cursor: str | None = None, q: str | None = None) -> CatalogBrandPage: + """One page of brands, by identifier or, with ``q``, those whose name starts with it.""" + return self._sdk._call(list_catalog_brands, **_query(limit=limit, cursor=cursor, q=q)) # noqa: SLF001 + + def iter_brands(self, *, limit: int | None = None, q: str | None = None) -> Iterator[CatalogBrand]: + """Every brand, page after page, with the same filters.""" + return paginate(lambda cursor: self.brands(limit=limit, cursor=cursor, q=q)) + + def sizes( + self, *, limit: int | None = None, cursor: str | None = None, category_id: int | None = None + ) -> CatalogSizePage: + """One page of sizes, each with its size group.""" + return self._sdk._call( # noqa: SLF001 + list_catalog_sizes, **_query(limit=limit, cursor=cursor, category_id=category_id) + ) + + def iter_sizes(self, *, limit: int | None = None, category_id: int | None = None) -> Iterator[CatalogSize]: + """Every size, page after page, with the same filters.""" + return paginate(lambda cursor: self.sizes(limit=limit, cursor=cursor, category_id=category_id)) + + def colors( + self, *, limit: int | None = None, cursor: str | None = None, category_id: int | None = None + ) -> CatalogValuePage: + """One page of colors.""" + return self._sdk._call( # noqa: SLF001 + list_catalog_colors, **_query(limit=limit, cursor=cursor, category_id=category_id) + ) + + def iter_colors(self, *, limit: int | None = None, category_id: int | None = None) -> Iterator[CatalogValue]: + """Every one of the colors, page after page, with the same filters.""" + return paginate(lambda cursor: self.colors(limit=limit, cursor=cursor, category_id=category_id)) + + def conditions( + self, *, limit: int | None = None, cursor: str | None = None, category_id: int | None = None + ) -> CatalogValuePage: + """One page of conditions.""" + return self._sdk._call( # noqa: SLF001 + list_catalog_conditions, **_query(limit=limit, cursor=cursor, category_id=category_id) + ) + + def iter_conditions(self, *, limit: int | None = None, category_id: int | None = None) -> Iterator[CatalogValue]: + """Every one of the conditions, page after page, with the same filters.""" + return paginate(lambda cursor: self.conditions(limit=limit, cursor=cursor, category_id=category_id)) + + def package_sizes( + self, *, limit: int | None = None, cursor: str | None = None, category_id: int | None = None + ) -> CatalogValuePage: + """One page of package sizes.""" + return self._sdk._call( # noqa: SLF001 + list_catalog_package_sizes, **_query(limit=limit, cursor=cursor, category_id=category_id) + ) + + def iter_package_sizes(self, *, limit: int | None = None, category_id: int | None = None) -> Iterator[CatalogValue]: + """Every one of the package sizes, page after page, with the same filters.""" + return paginate(lambda cursor: self.package_sizes(limit=limit, cursor=cursor, category_id=category_id)) + + def materials( + self, *, limit: int | None = None, cursor: str | None = None, category_id: int | None = None + ) -> CatalogValuePage: + """One page of materials.""" + return self._sdk._call( # noqa: SLF001 + list_catalog_materials, **_query(limit=limit, cursor=cursor, category_id=category_id) + ) + + def iter_materials(self, *, limit: int | None = None, category_id: int | None = None) -> Iterator[CatalogValue]: + """Every one of the materials, page after page, with the same filters.""" + return paginate(lambda cursor: self.materials(limit=limit, cursor=cursor, category_id=category_id)) + + +class _Webhooks: + """The seller's webhook endpoints, their secrets and deliveries, and the recent events. + + Reads need the ``webhooks:read`` scope, writes ``webhooks:write``. + """ + + def __init__(self, sdk: ControlResell) -> None: + self._sdk = sdk + + def endpoints(self) -> WebhookEndpointPage: + """The seller's endpoints, without their secrets (at most 5: a single page).""" + return self._sdk._call(list_webhook_endpoints) # noqa: SLF001 + + def endpoint(self, id: UUID | str) -> WebhookEndpoint: + """One endpoint by its identifier.""" + return self._sdk._call(get_webhook_endpoint, id=UUID(str(id))) # noqa: SLF001 + + def create_endpoint( + self, body: WebhookEndpointCreateRequest, *, idempotency_key: str | None = None + ) -> CreatedWebhookEndpoint: + """Creates an endpoint; the answer carries its signing secret (``secret`` reads it again).""" + return self._sdk._call( # noqa: SLF001 + create_webhook_endpoint, body=body, idempotency_key=_key(idempotency_key) + ) + + def update_endpoint(self, id: UUID | str, body: WebhookEndpointUpdateRequest) -> WebhookEndpoint: + """Updates the given fields of an endpoint (a JSON merge patch: ``description=None`` clears it). + + ``status="enabled"`` re-enables a disabled endpoint and resets its health. + """ + return self._sdk._call(update_webhook_endpoint, id=UUID(str(id)), body=body) # noqa: SLF001 + + def delete_endpoint(self, id: UUID | str) -> None: + """Deletes an endpoint; its pending deliveries are dropped.""" + self._sdk._call(delete_webhook_endpoint, id=UUID(str(id))) # noqa: SLF001 + + def secret(self, id: UUID | str) -> WebhookSecret: + """The current signing secret of an endpoint.""" + return self._sdk._call(get_webhook_secret, id=UUID(str(id))) # noqa: SLF001 + + def rotate_secret( + self, + id: UUID | str, + *, + expires_in_hours: int | None = None, + idempotency_key: str | None = None, + ) -> WebhookSecret: + """Gives an endpoint a new secret; the previous one stays valid ``expires_in_hours`` (24 by default, 0 at once).""" + body = WebhookSecretRotateRequest() if expires_in_hours is None else WebhookSecretRotateRequest( + expires_in_hours=expires_in_hours + ) + return self._sdk._call( # noqa: SLF001 + rotate_webhook_secret, id=UUID(str(id)), body=body, idempotency_key=_key(idempotency_key) + ) + + def test(self, id: UUID | str) -> WebhookTestResult: + """Sends a ``webhook.test`` event to the endpoint now and returns how it answered.""" + return self._sdk._call(test_webhook_endpoint, id=UUID(str(id))) # noqa: SLF001 + + def deliveries( + self, + id: UUID | str, + *, + limit: int | None = None, + cursor: str | None = None, + status: str | None = None, + type: str | None = None, # noqa: A002 + ) -> WebhookDeliveryPage: + """One page of the deliveries of an endpoint over the last 7 days, the most recent first.""" + return self._sdk._call( # noqa: SLF001 + list_webhook_deliveries, + id=UUID(str(id)), + **_query(limit=limit, cursor=cursor, status=status, type_=type), + ) + + def iter_deliveries( + self, + id: UUID | str, + *, + limit: int | None = None, + status: str | None = None, + type: str | None = None, # noqa: A002 + ) -> Iterator[WebhookDelivery]: + """Every delivery of an endpoint, page after page, with the same filters.""" + return paginate(lambda cursor: self.deliveries(id, limit=limit, cursor=cursor, status=status, type=type)) + + def retry_delivery( + self, id: UUID | str, delivery_id: UUID | str, *, idempotency_key: str | None = None + ) -> WebhookDelivery: + """Sends one event to the endpoint again, with the same ``webhook-id``.""" + return self._sdk._call( # noqa: SLF001 + retry_webhook_delivery, + id=UUID(str(id)), + delivery_id=UUID(str(delivery_id)), + idempotency_key=_key(idempotency_key), + ) + + def recover( + self, id: UUID | str, since: datetime.datetime, *, idempotency_key: str | None = None + ) -> WebhookRecovery: + """Sends again the failed deliveries since ``since`` (7 days at most, 1,000 per call: call again while ``has_more``).""" + return self._sdk._call( # noqa: SLF001 + recover_webhook_deliveries, + id=UUID(str(id)), + body=WebhookRecoverRequest(since=_utc(since)), + idempotency_key=_key(idempotency_key), + ) + + def events( + self, + *, + limit: int | None = None, + cursor: str | None = None, + since: datetime.datetime | None = None, + types: list[str] | None = None, + ) -> WebhookEventPage: + """One page of the events of the last 7 days, the oldest first: what a client that was offline catches up.""" + return self._sdk._call( # noqa: SLF001 + list_webhook_events, + **_query(limit=limit, cursor=cursor, since=_utc(since), type_=",".join(types) if types else None), + ) + + def iter_events( + self, *, limit: int | None = None, since: datetime.datetime | None = None, types: list[str] | None = None + ) -> Iterator[WebhookEvent]: + """Every event, page after page, with the same filters.""" + return paginate(lambda cursor: self.events(limit=limit, cursor=cursor, since=since, types=types)) + + def event_types(self) -> WebhookEventTypeList: + """The catalog of event types and the scope each one needs.""" + return self._sdk._call(list_webhook_event_types) # noqa: SLF001 diff --git a/src/controlresell/generated/api/catalogs/__init__.py b/src/controlresell/generated/api/catalogs/__init__.py new file mode 100644 index 0000000..2d7c0b2 --- /dev/null +++ b/src/controlresell/generated/api/catalogs/__init__.py @@ -0,0 +1 @@ +"""Contains endpoint functions for accessing the API""" diff --git a/src/controlresell/generated/api/catalogs/get_catalog_category.py b/src/controlresell/generated/api/catalogs/get_catalog_category.py new file mode 100644 index 0000000..af787f4 --- /dev/null +++ b/src/controlresell/generated/api/catalogs/get_catalog_category.py @@ -0,0 +1,197 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_category import CatalogCategory +from ...models.error_response import ErrorResponse +from ...types import Response + + +def _get_kwargs( + id: int, +) -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/categories/{id}".format( + id=quote(str(id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogCategory | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogCategory.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogCategory | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: int, + *, + client: AuthenticatedClient | Client, +) -> Response[CatalogCategory | ErrorResponse]: + """Read one category + + One category of the catalog, by its identifier. Requires `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogCategory | ErrorResponse] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: int, + *, + client: AuthenticatedClient | Client, +) -> CatalogCategory | ErrorResponse | None: + """Read one category + + One category of the catalog, by its identifier. Requires `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogCategory | ErrorResponse + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: int, + *, + client: AuthenticatedClient | Client, +) -> Response[CatalogCategory | ErrorResponse]: + """Read one category + + One category of the catalog, by its identifier. Requires `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogCategory | ErrorResponse] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: int, + *, + client: AuthenticatedClient | Client, +) -> CatalogCategory | ErrorResponse | None: + """Read one category + + One category of the catalog, by its identifier. Requires `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogCategory | ErrorResponse + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/get_catalog_category_fields.py b/src/controlresell/generated/api/catalogs/get_catalog_category_fields.py new file mode 100644 index 0000000..03cc19f --- /dev/null +++ b/src/controlresell/generated/api/catalogs/get_catalog_category_fields.py @@ -0,0 +1,217 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_category_fields import CatalogCategoryFields +from ...models.error_response import ErrorResponse +from ...types import Response + + +def _get_kwargs( + id: int, +) -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/categories/{id}/fields".format( + id=quote(str(id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogCategoryFields | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogCategoryFields.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogCategoryFields | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: int, + *, + client: AuthenticatedClient | Client, +) -> Response[CatalogCategoryFields | ErrorResponse]: + """Read what an item of a category is filled with + + Everything an item of this category takes beyond its common fields: its size groups (`sizeId`), its + enumerated fields with their values, each naming the item field it is written in (`colorIds`, + `materialIds`, `state`, `packageSizeId`, or an `enumValues` entry `{"enumKey": field.key, + "enumValue": value.key}`), its free-text fields (`attributes`, with whether a marketplace requires + them) and the measurements. A field used on one marketplace only names it in `platform`. Requires + `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogCategoryFields | ErrorResponse] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: int, + *, + client: AuthenticatedClient | Client, +) -> CatalogCategoryFields | ErrorResponse | None: + """Read what an item of a category is filled with + + Everything an item of this category takes beyond its common fields: its size groups (`sizeId`), its + enumerated fields with their values, each naming the item field it is written in (`colorIds`, + `materialIds`, `state`, `packageSizeId`, or an `enumValues` entry `{"enumKey": field.key, + "enumValue": value.key}`), its free-text fields (`attributes`, with whether a marketplace requires + them) and the measurements. A field used on one marketplace only names it in `platform`. Requires + `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogCategoryFields | ErrorResponse + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: int, + *, + client: AuthenticatedClient | Client, +) -> Response[CatalogCategoryFields | ErrorResponse]: + """Read what an item of a category is filled with + + Everything an item of this category takes beyond its common fields: its size groups (`sizeId`), its + enumerated fields with their values, each naming the item field it is written in (`colorIds`, + `materialIds`, `state`, `packageSizeId`, or an `enumValues` entry `{"enumKey": field.key, + "enumValue": value.key}`), its free-text fields (`attributes`, with whether a marketplace requires + them) and the measurements. A field used on one marketplace only names it in `platform`. Requires + `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogCategoryFields | ErrorResponse] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: int, + *, + client: AuthenticatedClient | Client, +) -> CatalogCategoryFields | ErrorResponse | None: + """Read what an item of a category is filled with + + Everything an item of this category takes beyond its common fields: its size groups (`sizeId`), its + enumerated fields with their values, each naming the item field it is written in (`colorIds`, + `materialIds`, `state`, `packageSizeId`, or an `enumValues` entry `{"enumKey": field.key, + "enumValue": value.key}`), its free-text fields (`attributes`, with whether a marketplace requires + them) and the measurements. A field used on one marketplace only names it in `platform`. Requires + `items:read`. + + Args: + id (int): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogCategoryFields | ErrorResponse + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_brands.py b/src/controlresell/generated/api/catalogs/list_catalog_brands.py new file mode 100644 index 0000000..c4166e7 --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_brands.py @@ -0,0 +1,235 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_brand_page import CatalogBrandPage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + q: str | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["q"] = q + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/brands", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogBrandPage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogBrandPage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogBrandPage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + q: str | Unset = UNSET, +) -> Response[CatalogBrandPage | ErrorResponse]: + """List the brands + + The brands an item's `brandId` takes: the global ones and the seller's own (`custom`), by + identifier, or with `q` the brands whose name starts with it, by name (case and accents ignored). + Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + q (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogBrandPage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + q=q, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + q: str | Unset = UNSET, +) -> CatalogBrandPage | ErrorResponse | None: + """List the brands + + The brands an item's `brandId` takes: the global ones and the seller's own (`custom`), by + identifier, or with `q` the brands whose name starts with it, by name (case and accents ignored). + Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + q (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogBrandPage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + q=q, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + q: str | Unset = UNSET, +) -> Response[CatalogBrandPage | ErrorResponse]: + """List the brands + + The brands an item's `brandId` takes: the global ones and the seller's own (`custom`), by + identifier, or with `q` the brands whose name starts with it, by name (case and accents ignored). + Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + q (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogBrandPage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + q=q, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + q: str | Unset = UNSET, +) -> CatalogBrandPage | ErrorResponse | None: + """List the brands + + The brands an item's `brandId` takes: the global ones and the seller's own (`custom`), by + identifier, or with `q` the brands whose name starts with it, by name (case and accents ignored). + Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + q (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogBrandPage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + q=q, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_categories.py b/src/controlresell/generated/api/catalogs/list_catalog_categories.py new file mode 100644 index 0000000..497bbbb --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_categories.py @@ -0,0 +1,259 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_category_page import CatalogCategoryPage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + parent_id: int | Unset = UNSET, + platform: str | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["parentId"] = parent_id + + params["platform"] = platform + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/categories", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogCategoryPage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogCategoryPage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogCategoryPage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + parent_id: int | Unset = UNSET, + platform: str | Unset = UNSET, +) -> Response[CatalogCategoryPage | ErrorResponse]: + """List the catalog's categories + + The categories an item's `categoryId` takes, flat, by identifier; each names its parent, so the tree + is rebuilt from the pages (or read level by level with `parentId`). One catalog for every + marketplace: `platforms` names where the category already has a mapping. Titles in the seller's + language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + parent_id (int | Unset): + platform (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogCategoryPage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + parent_id=parent_id, + platform=platform, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + parent_id: int | Unset = UNSET, + platform: str | Unset = UNSET, +) -> CatalogCategoryPage | ErrorResponse | None: + """List the catalog's categories + + The categories an item's `categoryId` takes, flat, by identifier; each names its parent, so the tree + is rebuilt from the pages (or read level by level with `parentId`). One catalog for every + marketplace: `platforms` names where the category already has a mapping. Titles in the seller's + language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + parent_id (int | Unset): + platform (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogCategoryPage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + parent_id=parent_id, + platform=platform, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + parent_id: int | Unset = UNSET, + platform: str | Unset = UNSET, +) -> Response[CatalogCategoryPage | ErrorResponse]: + """List the catalog's categories + + The categories an item's `categoryId` takes, flat, by identifier; each names its parent, so the tree + is rebuilt from the pages (or read level by level with `parentId`). One catalog for every + marketplace: `platforms` names where the category already has a mapping. Titles in the seller's + language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + parent_id (int | Unset): + platform (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogCategoryPage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + parent_id=parent_id, + platform=platform, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + parent_id: int | Unset = UNSET, + platform: str | Unset = UNSET, +) -> CatalogCategoryPage | ErrorResponse | None: + """List the catalog's categories + + The categories an item's `categoryId` takes, flat, by identifier; each names its parent, so the tree + is rebuilt from the pages (or read level by level with `parentId`). One catalog for every + marketplace: `platforms` names where the category already has a mapping. Titles in the seller's + language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + parent_id (int | Unset): + platform (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogCategoryPage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + parent_id=parent_id, + platform=platform, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_colors.py b/src/controlresell/generated/api/catalogs/list_catalog_colors.py new file mode 100644 index 0000000..0408047 --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_colors.py @@ -0,0 +1,236 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_value_page import CatalogValuePage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["categoryId"] = category_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/colors", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogValuePage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogValuePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogValuePage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the colors + + The colors an item's `colorIds` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the colors + + The colors an item's `colorIds` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the colors + + The colors an item's `colorIds` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the colors + + The colors an item's `colorIds` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_conditions.py b/src/controlresell/generated/api/catalogs/list_catalog_conditions.py new file mode 100644 index 0000000..8d11688 --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_conditions.py @@ -0,0 +1,236 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_value_page import CatalogValuePage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["categoryId"] = category_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/conditions", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogValuePage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogValuePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogValuePage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the conditions + + The conditions an item's `state` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the conditions + + The conditions an item's `state` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the conditions + + The conditions an item's `state` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the conditions + + The conditions an item's `state` takes (their `id`), by identifier; with `categoryId`, only those + that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_materials.py b/src/controlresell/generated/api/catalogs/list_catalog_materials.py new file mode 100644 index 0000000..365d90b --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_materials.py @@ -0,0 +1,236 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_value_page import CatalogValuePage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["categoryId"] = category_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/materials", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogValuePage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogValuePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogValuePage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the materials + + The materials an item's `materialIds` takes (their `id`), by identifier; with `categoryId`, only + those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the materials + + The materials an item's `materialIds` takes (their `id`), by identifier; with `categoryId`, only + those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the materials + + The materials an item's `materialIds` takes (their `id`), by identifier; with `categoryId`, only + those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the materials + + The materials an item's `materialIds` takes (their `id`), by identifier; with `categoryId`, only + those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_package_sizes.py b/src/controlresell/generated/api/catalogs/list_catalog_package_sizes.py new file mode 100644 index 0000000..930e353 --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_package_sizes.py @@ -0,0 +1,236 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_value_page import CatalogValuePage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["categoryId"] = category_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/package-sizes", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogValuePage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogValuePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogValuePage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the package sizes + + The package sizes an item's `packageSizeId` takes (their `id`), by identifier; with `categoryId`, + only those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the package sizes + + The package sizes an item's `packageSizeId` takes (their `id`), by identifier; with `categoryId`, + only those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogValuePage | ErrorResponse]: + """List the package sizes + + The package sizes an item's `packageSizeId` takes (their `id`), by identifier; with `categoryId`, + only those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogValuePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogValuePage | ErrorResponse | None: + """List the package sizes + + The package sizes an item's `packageSizeId` takes (their `id`), by identifier; with `categoryId`, + only those that apply to that category. Titles in the seller's language. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogValuePage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ) + ).parsed diff --git a/src/controlresell/generated/api/catalogs/list_catalog_sizes.py b/src/controlresell/generated/api/catalogs/list_catalog_sizes.py new file mode 100644 index 0000000..fe3f48a --- /dev/null +++ b/src/controlresell/generated/api/catalogs/list_catalog_sizes.py @@ -0,0 +1,236 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.catalog_size_page import CatalogSizePage +from ...models.error_response import ErrorResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + params["categoryId"] = category_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/catalogs/sizes", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CatalogSizePage | ErrorResponse: + if response.status_code == 200: + response_200 = CatalogSizePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CatalogSizePage | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogSizePage | ErrorResponse]: + """List the sizes + + The sizes an item's `sizeId` takes, by identifier, each with its size group; with `categoryId`, only + the sizes of that category's size groups. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogSizePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogSizePage | ErrorResponse | None: + """List the sizes + + The sizes an item's `sizeId` takes, by identifier, each with its size group; with `categoryId`, only + the sizes of that category's size groups. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogSizePage | ErrorResponse + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> Response[CatalogSizePage | ErrorResponse]: + """List the sizes + + The sizes an item's `sizeId` takes, by identifier, each with its size group; with `categoryId`, only + the sizes of that category's size groups. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CatalogSizePage | ErrorResponse] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + category_id=category_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + category_id: int | Unset = UNSET, +) -> CatalogSizePage | ErrorResponse | None: + """List the sizes + + The sizes an item's `sizeId` takes, by identifier, each with its size group; with `categoryId`, only + the sizes of that category's size groups. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + category_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CatalogSizePage | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + category_id=category_id, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/__init__.py b/src/controlresell/generated/api/webhooks/__init__.py new file mode 100644 index 0000000..2d7c0b2 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/__init__.py @@ -0,0 +1 @@ +"""Contains endpoint functions for accessing the API""" diff --git a/src/controlresell/generated/api/webhooks/create_webhook_endpoint.py b/src/controlresell/generated/api/webhooks/create_webhook_endpoint.py new file mode 100644 index 0000000..125559f --- /dev/null +++ b/src/controlresell/generated/api/webhooks/create_webhook_endpoint.py @@ -0,0 +1,242 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.created_webhook_endpoint import CreatedWebhookEndpoint +from ...models.error_response import ErrorResponse +from ...models.webhook_endpoint_create_request import WebhookEndpointCreateRequest +from ...types import Response + + +def _get_kwargs( + *, + body: WebhookEndpointCreateRequest, + idempotency_key: str, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/api/public/v1/webhook-endpoints", + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CreatedWebhookEndpoint | ErrorResponse: + if response.status_code == 201: + response_201 = CreatedWebhookEndpoint.from_dict(response.json()) + + return response_201 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if response.status_code == 503: + response_503 = ErrorResponse.from_dict(response.json()) + + return response_503 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CreatedWebhookEndpoint | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointCreateRequest, + idempotency_key: str, +) -> Response[CreatedWebhookEndpoint | ErrorResponse]: + """Create a webhook endpoint + + Registers an `https` URL that receives the seller's events, signed with the secret this response + gives (`Cache-Control: no-store`; read it again with `GET /webhook-endpoints/{id}/secret`). + `eventTypes` lists the types (`GET /webhook-event-types`) or is `["*"]` for all; the key must be + able to read the object of each type. `payloadMode` is `light` (the default) or `full`. 5 endpoints + at most per seller. Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + idempotency_key (str): + body (WebhookEndpointCreateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CreatedWebhookEndpoint | ErrorResponse] + """ + + kwargs = _get_kwargs( + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointCreateRequest, + idempotency_key: str, +) -> CreatedWebhookEndpoint | ErrorResponse | None: + """Create a webhook endpoint + + Registers an `https` URL that receives the seller's events, signed with the secret this response + gives (`Cache-Control: no-store`; read it again with `GET /webhook-endpoints/{id}/secret`). + `eventTypes` lists the types (`GET /webhook-event-types`) or is `["*"]` for all; the key must be + able to read the object of each type. `payloadMode` is `light` (the default) or `full`. 5 endpoints + at most per seller. Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + idempotency_key (str): + body (WebhookEndpointCreateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CreatedWebhookEndpoint | ErrorResponse + """ + + return sync_detailed( + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointCreateRequest, + idempotency_key: str, +) -> Response[CreatedWebhookEndpoint | ErrorResponse]: + """Create a webhook endpoint + + Registers an `https` URL that receives the seller's events, signed with the secret this response + gives (`Cache-Control: no-store`; read it again with `GET /webhook-endpoints/{id}/secret`). + `eventTypes` lists the types (`GET /webhook-event-types`) or is `["*"]` for all; the key must be + able to read the object of each type. `payloadMode` is `light` (the default) or `full`. 5 endpoints + at most per seller. Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + idempotency_key (str): + body (WebhookEndpointCreateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CreatedWebhookEndpoint | ErrorResponse] + """ + + kwargs = _get_kwargs( + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointCreateRequest, + idempotency_key: str, +) -> CreatedWebhookEndpoint | ErrorResponse | None: + """Create a webhook endpoint + + Registers an `https` URL that receives the seller's events, signed with the secret this response + gives (`Cache-Control: no-store`; read it again with `GET /webhook-endpoints/{id}/secret`). + `eventTypes` lists the types (`GET /webhook-event-types`) or is `["*"]` for all; the key must be + able to read the object of each type. `payloadMode` is `light` (the default) or `full`. 5 endpoints + at most per seller. Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + idempotency_key (str): + body (WebhookEndpointCreateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CreatedWebhookEndpoint | ErrorResponse + """ + + return ( + await asyncio_detailed( + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/delete_webhook_endpoint.py b/src/controlresell/generated/api/webhooks/delete_webhook_endpoint.py new file mode 100644 index 0000000..c15e8e6 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/delete_webhook_endpoint.py @@ -0,0 +1,200 @@ +from http import HTTPStatus +from typing import Any, cast +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...types import Response + + +def _get_kwargs( + id: UUID, +) -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "delete", + "url": "/api/public/v1/webhook-endpoints/{id}".format( + id=quote(str(id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Any | ErrorResponse: + if response.status_code == 204: + response_204 = cast(Any, None) + return response_204 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[Any | ErrorResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[Any | ErrorResponse]: + """Delete a webhook endpoint + + Deletes the endpoint; its pending deliveries are abandoned. Open without the plan. Requires + `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any | ErrorResponse] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Any | ErrorResponse | None: + """Delete a webhook endpoint + + Deletes the endpoint; its pending deliveries are abandoned. Open without the plan. Requires + `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Any | ErrorResponse + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[Any | ErrorResponse]: + """Delete a webhook endpoint + + Deletes the endpoint; its pending deliveries are abandoned. Open without the plan. Requires + `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[Any | ErrorResponse] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Any | ErrorResponse | None: + """Delete a webhook endpoint + + Deletes the endpoint; its pending deliveries are abandoned. Open without the plan. Requires + `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Any | ErrorResponse + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/get_webhook_endpoint.py b/src/controlresell/generated/api/webhooks/get_webhook_endpoint.py new file mode 100644 index 0000000..23f6ed3 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/get_webhook_endpoint.py @@ -0,0 +1,197 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_endpoint import WebhookEndpoint +from ...types import Response + + +def _get_kwargs( + id: UUID, +) -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/webhook-endpoints/{id}".format( + id=quote(str(id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookEndpoint: + if response.status_code == 200: + response_200 = WebhookEndpoint.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookEndpoint]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookEndpoint]: + """Read one webhook endpoint + + One endpoint of the seller, its status and why it is disabled, without its secret. Open without the + plan. Requires `webhooks:read`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEndpoint] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookEndpoint | None: + """Read one webhook endpoint + + One endpoint of the seller, its status and why it is disabled, without its secret. Open without the + plan. Requires `webhooks:read`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEndpoint + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookEndpoint]: + """Read one webhook endpoint + + One endpoint of the seller, its status and why it is disabled, without its secret. Open without the + plan. Requires `webhooks:read`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEndpoint] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookEndpoint | None: + """Read one webhook endpoint + + One endpoint of the seller, its status and why it is disabled, without its secret. Open without the + plan. Requires `webhooks:read`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEndpoint + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/get_webhook_secret.py b/src/controlresell/generated/api/webhooks/get_webhook_secret.py new file mode 100644 index 0000000..5c19bc2 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/get_webhook_secret.py @@ -0,0 +1,206 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_secret import WebhookSecret +from ...types import Response + + +def _get_kwargs( + id: UUID, +) -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/webhook-endpoints/{id}/secret".format( + id=quote(str(id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookSecret: + if response.status_code == 200: + response_200 = WebhookSecret.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookSecret]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookSecret]: + """Read the signing secret of a webhook endpoint + + The current signing secret (`Cache-Control: no-store`), and until when the previous one still signs + after a rotation. Needs a key that can read everything the endpoint receives; the seller is told by + e-mail (once an hour at most). Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookSecret] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookSecret | None: + """Read the signing secret of a webhook endpoint + + The current signing secret (`Cache-Control: no-store`), and until when the previous one still signs + after a rotation. Needs a key that can read everything the endpoint receives; the seller is told by + e-mail (once an hour at most). Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookSecret + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookSecret]: + """Read the signing secret of a webhook endpoint + + The current signing secret (`Cache-Control: no-store`), and until when the previous one still signs + after a rotation. Needs a key that can read everything the endpoint receives; the seller is told by + e-mail (once an hour at most). Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookSecret] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookSecret | None: + """Read the signing secret of a webhook endpoint + + The current signing secret (`Cache-Control: no-store`), and until when the previous one still signs + after a rotation. Needs a key that can read everything the endpoint receives; the seller is told by + e-mail (once an hour at most). Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookSecret + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/list_webhook_deliveries.py b/src/controlresell/generated/api/webhooks/list_webhook_deliveries.py new file mode 100644 index 0000000..6920d79 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/list_webhook_deliveries.py @@ -0,0 +1,272 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_delivery_page import WebhookDeliveryPage +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + id: UUID, + *, + status: str | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["status"] = status + + params["type"] = type_ + + params["limit"] = limit + + params["cursor"] = cursor + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/webhook-endpoints/{id}/deliveries".format( + id=quote(str(id), safe=""), + ), + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookDeliveryPage: + if response.status_code == 200: + response_200 = WebhookDeliveryPage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookDeliveryPage]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + status: str | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> Response[ErrorResponse | WebhookDeliveryPage]: + """List the deliveries of a webhook endpoint + + The delivery log of the last 7 days, the most recent first, one page at a time: status, attempt, + HTTP status, duration and error, never the payload. Filters `status` (`pending`, `delivered`, + `failed`) and `type`. Requires `webhooks:read`. + + Args: + id (UUID): + status (str | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookDeliveryPage] + """ + + kwargs = _get_kwargs( + id=id, + status=status, + type_=type_, + limit=limit, + cursor=cursor, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, + status: str | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> ErrorResponse | WebhookDeliveryPage | None: + """List the deliveries of a webhook endpoint + + The delivery log of the last 7 days, the most recent first, one page at a time: status, attempt, + HTTP status, duration and error, never the payload. Filters `status` (`pending`, `delivered`, + `failed`) and `type`. Requires `webhooks:read`. + + Args: + id (UUID): + status (str | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookDeliveryPage + """ + + return sync_detailed( + id=id, + client=client, + status=status, + type_=type_, + limit=limit, + cursor=cursor, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + status: str | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> Response[ErrorResponse | WebhookDeliveryPage]: + """List the deliveries of a webhook endpoint + + The delivery log of the last 7 days, the most recent first, one page at a time: status, attempt, + HTTP status, duration and error, never the payload. Filters `status` (`pending`, `delivered`, + `failed`) and `type`. Requires `webhooks:read`. + + Args: + id (UUID): + status (str | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookDeliveryPage] + """ + + kwargs = _get_kwargs( + id=id, + status=status, + type_=type_, + limit=limit, + cursor=cursor, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, + status: str | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> ErrorResponse | WebhookDeliveryPage | None: + """List the deliveries of a webhook endpoint + + The delivery log of the last 7 days, the most recent first, one page at a time: status, attempt, + HTTP status, duration and error, never the payload. Filters `status` (`pending`, `delivered`, + `failed`) and `type`. Requires `webhooks:read`. + + Args: + id (UUID): + status (str | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookDeliveryPage + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + status=status, + type_=type_, + limit=limit, + cursor=cursor, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/list_webhook_endpoints.py b/src/controlresell/generated/api/webhooks/list_webhook_endpoints.py new file mode 100644 index 0000000..ed08e23 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/list_webhook_endpoints.py @@ -0,0 +1,168 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_endpoint_page import WebhookEndpointPage +from ...types import Response + + +def _get_kwargs() -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/webhook-endpoints", + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookEndpointPage: + if response.status_code == 200: + response_200 = WebhookEndpointPage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookEndpointPage]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookEndpointPage]: + """List the seller's webhook endpoints + + Every webhook endpoint of the seller (5 at most), without their secrets: one page, `nextCursor` is + always null. Open without the plan, so a seller can still see what receives their events. Requires + `webhooks:read`. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEndpointPage] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookEndpointPage | None: + """List the seller's webhook endpoints + + Every webhook endpoint of the seller (5 at most), without their secrets: one page, `nextCursor` is + always null. Open without the plan, so a seller can still see what receives their events. Requires + `webhooks:read`. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEndpointPage + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookEndpointPage]: + """List the seller's webhook endpoints + + Every webhook endpoint of the seller (5 at most), without their secrets: one page, `nextCursor` is + always null. Open without the plan, so a seller can still see what receives their events. Requires + `webhooks:read`. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEndpointPage] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookEndpointPage | None: + """List the seller's webhook endpoints + + Every webhook endpoint of the seller (5 at most), without their secrets: one page, `nextCursor` is + always null. Open without the plan, so a seller can still see what receives their events. Requires + `webhooks:read`. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEndpointPage + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/list_webhook_event_types.py b/src/controlresell/generated/api/webhooks/list_webhook_event_types.py new file mode 100644 index 0000000..4ff1c41 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/list_webhook_event_types.py @@ -0,0 +1,154 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_event_type_list import WebhookEventTypeList +from ...types import Response + + +def _get_kwargs() -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/webhook-event-types", + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookEventTypeList: + if response.status_code == 200: + response_200 = WebhookEventTypeList.from_dict(response.json()) + + return response_200 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookEventTypeList]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookEventTypeList]: + """List the webhook event types + + The catalogue of event types and the read scope each one needs; `webhook.test` is only sent by `POST + /webhook-endpoints/{id}/test`, never subscribed to. Open to every key, without the plan. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEventTypeList] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookEventTypeList | None: + """List the webhook event types + + The catalogue of event types and the read scope each one needs; `webhook.test` is only sent by `POST + /webhook-endpoints/{id}/test`, never subscribed to. Open to every key, without the plan. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEventTypeList + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookEventTypeList]: + """List the webhook event types + + The catalogue of event types and the read scope each one needs; `webhook.test` is only sent by `POST + /webhook-endpoints/{id}/test`, never subscribed to. Open to every key, without the plan. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEventTypeList] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookEventTypeList | None: + """List the webhook event types + + The catalogue of event types and the read scope each one needs; `webhook.test` is only sent by `POST + /webhook-endpoints/{id}/test`, never subscribed to. Open to every key, without the plan. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEventTypeList + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/list_webhook_events.py b/src/controlresell/generated/api/webhooks/list_webhook_events.py new file mode 100644 index 0000000..cfb6701 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/list_webhook_events.py @@ -0,0 +1,254 @@ +import datetime +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_event_page import WebhookEventPage +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + since: datetime.datetime | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + json_since: str | Unset = UNSET + if not isinstance(since, Unset): + json_since = since.isoformat() + params["since"] = json_since + + params["type"] = type_ + + params["limit"] = limit + + params["cursor"] = cursor + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/events", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookEventPage: + if response.status_code == 200: + response_200 = WebhookEventPage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookEventPage]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + since: datetime.datetime | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> Response[ErrorResponse | WebhookEventPage]: + """List the seller's events + + The events of the last 7 days, the oldest first from `since`, in the envelope of a light webhook + body: the way to catch up after being offline. Only the types the key can read (a type asked without + its scope is a 403); `type` takes several types, comma separated. + + Args: + since (datetime.datetime | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEventPage] + """ + + kwargs = _get_kwargs( + since=since, + type_=type_, + limit=limit, + cursor=cursor, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + since: datetime.datetime | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> ErrorResponse | WebhookEventPage | None: + """List the seller's events + + The events of the last 7 days, the oldest first from `since`, in the envelope of a light webhook + body: the way to catch up after being offline. Only the types the key can read (a type asked without + its scope is a 403); `type` takes several types, comma separated. + + Args: + since (datetime.datetime | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEventPage + """ + + return sync_detailed( + client=client, + since=since, + type_=type_, + limit=limit, + cursor=cursor, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + since: datetime.datetime | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> Response[ErrorResponse | WebhookEventPage]: + """List the seller's events + + The events of the last 7 days, the oldest first from `since`, in the envelope of a light webhook + body: the way to catch up after being offline. Only the types the key can read (a type asked without + its scope is a 403); `type` takes several types, comma separated. + + Args: + since (datetime.datetime | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEventPage] + """ + + kwargs = _get_kwargs( + since=since, + type_=type_, + limit=limit, + cursor=cursor, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + since: datetime.datetime | Unset = UNSET, + type_: str | Unset = UNSET, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, +) -> ErrorResponse | WebhookEventPage | None: + """List the seller's events + + The events of the last 7 days, the oldest first from `since`, in the envelope of a light webhook + body: the way to catch up after being offline. Only the types the key can read (a type asked without + its scope is a 403); `type` takes several types, comma separated. + + Args: + since (datetime.datetime | Unset): + type_ (str | Unset): + limit (int | Unset): Default: 50. + cursor (str | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEventPage + """ + + return ( + await asyncio_detailed( + client=client, + since=since, + type_=type_, + limit=limit, + cursor=cursor, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/recover_webhook_deliveries.py b/src/controlresell/generated/api/webhooks/recover_webhook_deliveries.py new file mode 100644 index 0000000..9d00b0a --- /dev/null +++ b/src/controlresell/generated/api/webhooks/recover_webhook_deliveries.py @@ -0,0 +1,251 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_recover_request import WebhookRecoverRequest +from ...models.webhook_recovery import WebhookRecovery +from ...types import Response + + +def _get_kwargs( + id: UUID, + *, + body: WebhookRecoverRequest, + idempotency_key: str, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/api/public/v1/webhook-endpoints/{id}/recover".format( + id=quote(str(id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookRecovery: + if response.status_code == 202: + response_202 = WebhookRecovery.from_dict(response.json()) + + return response_202 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if response.status_code == 503: + response_503 = ErrorResponse.from_dict(response.json()) + + return response_503 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookRecovery]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookRecoverRequest, + idempotency_key: str, +) -> Response[ErrorResponse | WebhookRecovery]: + """Send the failed deliveries again + + Sends again the `failed` deliveries of this endpoint since `since` (7 days back at most), the oldest + first, 1 000 at most per call: call again while `hasMore` is true. Requires `webhooks:write` and an + `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookRecoverRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookRecovery] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookRecoverRequest, + idempotency_key: str, +) -> ErrorResponse | WebhookRecovery | None: + """Send the failed deliveries again + + Sends again the `failed` deliveries of this endpoint since `since` (7 days back at most), the oldest + first, 1 000 at most per call: call again while `hasMore` is true. Requires `webhooks:write` and an + `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookRecoverRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookRecovery + """ + + return sync_detailed( + id=id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookRecoverRequest, + idempotency_key: str, +) -> Response[ErrorResponse | WebhookRecovery]: + """Send the failed deliveries again + + Sends again the `failed` deliveries of this endpoint since `since` (7 days back at most), the oldest + first, 1 000 at most per call: call again while `hasMore` is true. Requires `webhooks:write` and an + `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookRecoverRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookRecovery] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookRecoverRequest, + idempotency_key: str, +) -> ErrorResponse | WebhookRecovery | None: + """Send the failed deliveries again + + Sends again the `failed` deliveries of this endpoint since `since` (7 days back at most), the oldest + first, 1 000 at most per call: call again while `hasMore` is true. Requires `webhooks:write` and an + `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookRecoverRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookRecovery + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/retry_webhook_delivery.py b/src/controlresell/generated/api/webhooks/retry_webhook_delivery.py new file mode 100644 index 0000000..405f597 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/retry_webhook_delivery.py @@ -0,0 +1,255 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_delivery import WebhookDelivery +from ...types import Response + + +def _get_kwargs( + id: UUID, + delivery_id: UUID, + *, + idempotency_key: str, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/api/public/v1/webhook-endpoints/{id}/deliveries/{delivery_id}/retry".format( + id=quote(str(id), safe=""), + delivery_id=quote(str(delivery_id), safe=""), + ), + } + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookDelivery: + if response.status_code == 202: + response_202 = WebhookDelivery.from_dict(response.json()) + + return response_202 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if response.status_code == 503: + response_503 = ErrorResponse.from_dict(response.json()) + + return response_503 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookDelivery]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + delivery_id: UUID, + *, + client: AuthenticatedClient | Client, + idempotency_key: str, +) -> Response[ErrorResponse | WebhookDelivery]: + """Send a delivery again + + Sends this event to this endpoint again, with the same `webhook-id`: a `failed` or `delivered` + delivery goes back to `pending`, its attempts from 1 again. A delivery still `pending` (a retry or a + recovery in progress) is already queued: it is not queued a second time, and is returned as it is, + its attempts unchanged. 409 when the endpoint is disabled, 410 `event_expired` past 7 days. Requires + `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + delivery_id (UUID): + idempotency_key (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookDelivery] + """ + + kwargs = _get_kwargs( + id=id, + delivery_id=delivery_id, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + delivery_id: UUID, + *, + client: AuthenticatedClient | Client, + idempotency_key: str, +) -> ErrorResponse | WebhookDelivery | None: + """Send a delivery again + + Sends this event to this endpoint again, with the same `webhook-id`: a `failed` or `delivered` + delivery goes back to `pending`, its attempts from 1 again. A delivery still `pending` (a retry or a + recovery in progress) is already queued: it is not queued a second time, and is returned as it is, + its attempts unchanged. 409 when the endpoint is disabled, 410 `event_expired` past 7 days. Requires + `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + delivery_id (UUID): + idempotency_key (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookDelivery + """ + + return sync_detailed( + id=id, + delivery_id=delivery_id, + client=client, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + id: UUID, + delivery_id: UUID, + *, + client: AuthenticatedClient | Client, + idempotency_key: str, +) -> Response[ErrorResponse | WebhookDelivery]: + """Send a delivery again + + Sends this event to this endpoint again, with the same `webhook-id`: a `failed` or `delivered` + delivery goes back to `pending`, its attempts from 1 again. A delivery still `pending` (a retry or a + recovery in progress) is already queued: it is not queued a second time, and is returned as it is, + its attempts unchanged. 409 when the endpoint is disabled, 410 `event_expired` past 7 days. Requires + `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + delivery_id (UUID): + idempotency_key (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookDelivery] + """ + + kwargs = _get_kwargs( + id=id, + delivery_id=delivery_id, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + delivery_id: UUID, + *, + client: AuthenticatedClient | Client, + idempotency_key: str, +) -> ErrorResponse | WebhookDelivery | None: + """Send a delivery again + + Sends this event to this endpoint again, with the same `webhook-id`: a `failed` or `delivered` + delivery goes back to `pending`, its attempts from 1 again. A delivery still `pending` (a retry or a + recovery in progress) is already queued: it is not queued a second time, and is returned as it is, + its attempts unchanged. 409 when the endpoint is disabled, 410 `event_expired` past 7 days. Requires + `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + delivery_id (UUID): + idempotency_key (str): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookDelivery + """ + + return ( + await asyncio_detailed( + id=id, + delivery_id=delivery_id, + client=client, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/rotate_webhook_secret.py b/src/controlresell/generated/api/webhooks/rotate_webhook_secret.py new file mode 100644 index 0000000..4f01320 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/rotate_webhook_secret.py @@ -0,0 +1,256 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_secret import WebhookSecret +from ...models.webhook_secret_rotate_request import WebhookSecretRotateRequest +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + id: UUID, + *, + body: WebhookSecretRotateRequest | Unset = UNSET, + idempotency_key: str, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/api/public/v1/webhook-endpoints/{id}/rotate-secret".format( + id=quote(str(id), safe=""), + ), + } + + if not isinstance(body, Unset): + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookSecret: + if response.status_code == 200: + response_200 = WebhookSecret.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if response.status_code == 503: + response_503 = ErrorResponse.from_dict(response.json()) + + return response_503 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookSecret]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookSecretRotateRequest | Unset = UNSET, + idempotency_key: str, +) -> Response[ErrorResponse | WebhookSecret]: + """Rotate the signing secret of a webhook endpoint + + A new signing secret, in this response (`Cache-Control: no-store`). The previous one keeps signing + too for `expiresInHours` (0 to 72, 24 by default), so the receiver can switch without losing a + delivery. Needs a key that can read everything the endpoint receives; the seller is told by e-mail. + Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookSecretRotateRequest | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookSecret] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookSecretRotateRequest | Unset = UNSET, + idempotency_key: str, +) -> ErrorResponse | WebhookSecret | None: + """Rotate the signing secret of a webhook endpoint + + A new signing secret, in this response (`Cache-Control: no-store`). The previous one keeps signing + too for `expiresInHours` (0 to 72, 24 by default), so the receiver can switch without losing a + delivery. Needs a key that can read everything the endpoint receives; the seller is told by e-mail. + Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookSecretRotateRequest | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookSecret + """ + + return sync_detailed( + id=id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookSecretRotateRequest | Unset = UNSET, + idempotency_key: str, +) -> Response[ErrorResponse | WebhookSecret]: + """Rotate the signing secret of a webhook endpoint + + A new signing secret, in this response (`Cache-Control: no-store`). The previous one keeps signing + too for `expiresInHours` (0 to 72, 24 by default), so the receiver can switch without losing a + delivery. Needs a key that can read everything the endpoint receives; the seller is told by e-mail. + Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookSecretRotateRequest | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookSecret] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookSecretRotateRequest | Unset = UNSET, + idempotency_key: str, +) -> ErrorResponse | WebhookSecret | None: + """Rotate the signing secret of a webhook endpoint + + A new signing secret, in this response (`Cache-Control: no-store`). The previous one keeps signing + too for `expiresInHours` (0 to 72, 24 by default), so the receiver can switch without losing a + delivery. Needs a key that can read everything the endpoint receives; the seller is told by e-mail. + Requires `webhooks:write` and an `Idempotency-Key`. + + Args: + id (UUID): + idempotency_key (str): + body (WebhookSecretRotateRequest | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookSecret + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/test_webhook_endpoint.py b/src/controlresell/generated/api/webhooks/test_webhook_endpoint.py new file mode 100644 index 0000000..6585743 --- /dev/null +++ b/src/controlresell/generated/api/webhooks/test_webhook_endpoint.py @@ -0,0 +1,206 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_test_result import WebhookTestResult +from ...types import Response + + +def _get_kwargs( + id: UUID, +) -> dict[str, Any]: + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/api/public/v1/webhook-endpoints/{id}/test".format( + id=quote(str(id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookTestResult: + if response.status_code == 200: + response_200 = WebhookTestResult.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookTestResult]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookTestResult]: + """Send a test event to a webhook endpoint + + Sends one signed `webhook.test` now and waits for the answer (10 seconds in all). An `Idempotency- + Key` is accepted and ignored: a test is never replayed. 429 `webhook_endpoint_busy` while the + endpoint already receives as many calls as it may. Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookTestResult] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookTestResult | None: + """Send a test event to a webhook endpoint + + Sends one signed `webhook.test` now and waits for the answer (10 seconds in all). An `Idempotency- + Key` is accepted and ignored: a test is never replayed. 429 `webhook_endpoint_busy` while the + endpoint already receives as many calls as it may. Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookTestResult + """ + + return sync_detailed( + id=id, + client=client, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> Response[ErrorResponse | WebhookTestResult]: + """Send a test event to a webhook endpoint + + Sends one signed `webhook.test` now and waits for the answer (10 seconds in all). An `Idempotency- + Key` is accepted and ignored: a test is never replayed. 429 `webhook_endpoint_busy` while the + endpoint already receives as many calls as it may. Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookTestResult] + """ + + kwargs = _get_kwargs( + id=id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, +) -> ErrorResponse | WebhookTestResult | None: + """Send a test event to a webhook endpoint + + Sends one signed `webhook.test` now and waits for the answer (10 seconds in all). An `Idempotency- + Key` is accepted and ignored: a test is never replayed. 429 `webhook_endpoint_busy` while the + endpoint already receives as many calls as it may. Requires `webhooks:write`. + + Args: + id (UUID): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookTestResult + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + ) + ).parsed diff --git a/src/controlresell/generated/api/webhooks/update_webhook_endpoint.py b/src/controlresell/generated/api/webhooks/update_webhook_endpoint.py new file mode 100644 index 0000000..e6317ef --- /dev/null +++ b/src/controlresell/generated/api/webhooks/update_webhook_endpoint.py @@ -0,0 +1,231 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.webhook_endpoint import WebhookEndpoint +from ...models.webhook_endpoint_update_request import WebhookEndpointUpdateRequest +from ...types import Response + + +def _get_kwargs( + id: UUID, + *, + body: WebhookEndpointUpdateRequest, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + _kwargs: dict[str, Any] = { + "method": "patch", + "url": "/api/public/v1/webhook-endpoints/{id}".format( + id=quote(str(id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | WebhookEndpoint: + if response.status_code == 200: + response_200 = WebhookEndpoint.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | WebhookEndpoint]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointUpdateRequest, +) -> Response[ErrorResponse | WebhookEndpoint]: + """Change a webhook endpoint + + A JSON merge patch: a field left out keeps its value, `description: null` clears it. Changing `url` + or `payloadMode` needs a key that can read everything the endpoint receives. `status` `disabled` + stops the deliveries (pending ones fail); `enabled` turns it back on, its failures reset. Only + `{"status": "disabled"}` is open without the plan. Requires `webhooks:write`. + + Args: + id (UUID): + body (WebhookEndpointUpdateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEndpoint] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointUpdateRequest, +) -> ErrorResponse | WebhookEndpoint | None: + """Change a webhook endpoint + + A JSON merge patch: a field left out keeps its value, `description: null` clears it. Changing `url` + or `payloadMode` needs a key that can read everything the endpoint receives. `status` `disabled` + stops the deliveries (pending ones fail); `enabled` turns it back on, its failures reset. Only + `{"status": "disabled"}` is open without the plan. Requires `webhooks:write`. + + Args: + id (UUID): + body (WebhookEndpointUpdateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEndpoint + """ + + return sync_detailed( + id=id, + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointUpdateRequest, +) -> Response[ErrorResponse | WebhookEndpoint]: + """Change a webhook endpoint + + A JSON merge patch: a field left out keeps its value, `description: null` clears it. Changing `url` + or `payloadMode` needs a key that can read everything the endpoint receives. `status` `disabled` + stops the deliveries (pending ones fail); `enabled` turns it back on, its failures reset. Only + `{"status": "disabled"}` is open without the plan. Requires `webhooks:write`. + + Args: + id (UUID): + body (WebhookEndpointUpdateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | WebhookEndpoint] + """ + + kwargs = _get_kwargs( + id=id, + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: UUID, + *, + client: AuthenticatedClient | Client, + body: WebhookEndpointUpdateRequest, +) -> ErrorResponse | WebhookEndpoint | None: + """Change a webhook endpoint + + A JSON merge patch: a field left out keeps its value, `description: null` clears it. Changing `url` + or `payloadMode` needs a key that can read everything the endpoint receives. `status` `disabled` + stops the deliveries (pending ones fail); `enabled` turns it back on, its failures reset. Only + `{"status": "disabled"}` is open without the plan. Requires `webhooks:write`. + + Args: + id (UUID): + body (WebhookEndpointUpdateRequest): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | WebhookEndpoint + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + body=body, + ) + ).parsed diff --git a/src/controlresell/generated/models/__init__.py b/src/controlresell/generated/models/__init__.py index 065e166..8abda0a 100644 --- a/src/controlresell/generated/models/__init__.py +++ b/src/controlresell/generated/models/__init__.py @@ -4,8 +4,21 @@ from .account_page import AccountPage from .api_error import ApiError from .api_error_params import ApiErrorParams +from .catalog_brand import CatalogBrand +from .catalog_brand_page import CatalogBrandPage +from .catalog_category import CatalogCategory +from .catalog_category_fields import CatalogCategoryFields +from .catalog_category_page import CatalogCategoryPage +from .catalog_enum_field import CatalogEnumField +from .catalog_measurement import CatalogMeasurement +from .catalog_size import CatalogSize +from .catalog_size_page import CatalogSizePage +from .catalog_text_field import CatalogTextField +from .catalog_value import CatalogValue +from .catalog_value_page import CatalogValuePage from .conversation import Conversation from .conversation_page import ConversationPage +from .created_webhook_endpoint import CreatedWebhookEndpoint from .customer import Customer from .customer_address import CustomerAddress from .customer_page import CustomerPage @@ -36,14 +49,43 @@ from .scheduled_action import ScheduledAction from .send_message_request import SendMessageRequest from .send_offer_request import SendOfferRequest +from .webhook_delivery import WebhookDelivery +from .webhook_delivery_page import WebhookDeliveryPage +from .webhook_endpoint import WebhookEndpoint +from .webhook_endpoint_create_request import WebhookEndpointCreateRequest +from .webhook_endpoint_page import WebhookEndpointPage +from .webhook_endpoint_update_request import WebhookEndpointUpdateRequest +from .webhook_event import WebhookEvent +from .webhook_event_data import WebhookEventData +from .webhook_event_page import WebhookEventPage +from .webhook_event_type import WebhookEventType +from .webhook_event_type_list import WebhookEventTypeList +from .webhook_recover_request import WebhookRecoverRequest +from .webhook_recovery import WebhookRecovery +from .webhook_secret import WebhookSecret +from .webhook_secret_rotate_request import WebhookSecretRotateRequest +from .webhook_test_result import WebhookTestResult __all__ = ( "Account", "AccountPage", "ApiError", "ApiErrorParams", + "CatalogBrand", + "CatalogBrandPage", + "CatalogCategory", + "CatalogCategoryFields", + "CatalogCategoryPage", + "CatalogEnumField", + "CatalogMeasurement", + "CatalogSize", + "CatalogSizePage", + "CatalogTextField", + "CatalogValue", + "CatalogValuePage", "Conversation", "ConversationPage", + "CreatedWebhookEndpoint", "Customer", "CustomerAddress", "CustomerPage", @@ -74,4 +116,20 @@ "ScheduledAction", "SendMessageRequest", "SendOfferRequest", + "WebhookDelivery", + "WebhookDeliveryPage", + "WebhookEndpoint", + "WebhookEndpointCreateRequest", + "WebhookEndpointPage", + "WebhookEndpointUpdateRequest", + "WebhookEvent", + "WebhookEventData", + "WebhookEventPage", + "WebhookEventType", + "WebhookEventTypeList", + "WebhookRecoverRequest", + "WebhookRecovery", + "WebhookSecret", + "WebhookSecretRotateRequest", + "WebhookTestResult", ) diff --git a/src/controlresell/generated/models/catalog_brand.py b/src/controlresell/generated/models/catalog_brand.py new file mode 100644 index 0000000..92ab501 --- /dev/null +++ b/src/controlresell/generated/models/catalog_brand.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="CatalogBrand") + + +@_attrs_define +class CatalogBrand: + """ + Attributes: + id (int): + name (str): + custom (bool): + """ + + id: int + name: str + custom: bool + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + name = self.name + + custom = self.custom + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "name": name, + "custom": custom, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + id = d.pop("id") + + name = d.pop("name") + + custom = d.pop("custom") + + catalog_brand = cls( + id=id, + name=name, + custom=custom, + ) + + catalog_brand.additional_properties = d + return catalog_brand + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_brand_page.py b/src/controlresell/generated/models/catalog_brand_page.py new file mode 100644 index 0000000..44aec44 --- /dev/null +++ b/src/controlresell/generated/models/catalog_brand_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.catalog_brand import CatalogBrand + + +T = TypeVar("T", bound="CatalogBrandPage") + + +@_attrs_define +class CatalogBrandPage: + """ + Attributes: + data (list[CatalogBrand]): + next_cursor (None | str | Unset): + """ + + data: list[CatalogBrand] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.catalog_brand import CatalogBrand + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = CatalogBrand.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + catalog_brand_page = cls( + data=data, + next_cursor=next_cursor, + ) + + catalog_brand_page.additional_properties = d + return catalog_brand_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_category.py b/src/controlresell/generated/models/catalog_category.py new file mode 100644 index 0000000..409fe70 --- /dev/null +++ b/src/controlresell/generated/models/catalog_category.py @@ -0,0 +1,115 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="CatalogCategory") + + +@_attrs_define +class CatalogCategory: + """ + Attributes: + id (int): + title (str): + has_children (bool): + size_group_ids (list[int]): + platforms (list[str]): + parent_id (int | None | Unset): + """ + + id: int + title: str + has_children: bool + size_group_ids: list[int] + platforms: list[str] + parent_id: int | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + title = self.title + + has_children = self.has_children + + size_group_ids = self.size_group_ids + + platforms = self.platforms + + parent_id: int | None | Unset + if isinstance(self.parent_id, Unset): + parent_id = UNSET + else: + parent_id = self.parent_id + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "title": title, + "hasChildren": has_children, + "sizeGroupIds": size_group_ids, + "platforms": platforms, + } + ) + if parent_id is not UNSET: + field_dict["parentId"] = parent_id + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + id = d.pop("id") + + title = d.pop("title") + + has_children = d.pop("hasChildren") + + size_group_ids = cast(list[int], d.pop("sizeGroupIds")) + + platforms = cast(list[str], d.pop("platforms")) + + def _parse_parent_id(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + parent_id = _parse_parent_id(d.pop("parentId", UNSET)) + + catalog_category = cls( + id=id, + title=title, + has_children=has_children, + size_group_ids=size_group_ids, + platforms=platforms, + parent_id=parent_id, + ) + + catalog_category.additional_properties = d + return catalog_category + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_category_fields.py b/src/controlresell/generated/models/catalog_category_fields.py new file mode 100644 index 0000000..eb0913e --- /dev/null +++ b/src/controlresell/generated/models/catalog_category_fields.py @@ -0,0 +1,127 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.catalog_enum_field import CatalogEnumField + from ..models.catalog_measurement import CatalogMeasurement + from ..models.catalog_text_field import CatalogTextField + + +T = TypeVar("T", bound="CatalogCategoryFields") + + +@_attrs_define +class CatalogCategoryFields: + """ + Attributes: + category_id (int): + size_group_ids (list[int]): + enum_fields (list[CatalogEnumField]): + text_fields (list[CatalogTextField]): + measurements (list[CatalogMeasurement]): + """ + + category_id: int + size_group_ids: list[int] + enum_fields: list[CatalogEnumField] + text_fields: list[CatalogTextField] + measurements: list[CatalogMeasurement] + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + category_id = self.category_id + + size_group_ids = self.size_group_ids + + enum_fields = [] + for enum_fields_item_data in self.enum_fields: + enum_fields_item = enum_fields_item_data.to_dict() + enum_fields.append(enum_fields_item) + + text_fields = [] + for text_fields_item_data in self.text_fields: + text_fields_item = text_fields_item_data.to_dict() + text_fields.append(text_fields_item) + + measurements = [] + for measurements_item_data in self.measurements: + measurements_item = measurements_item_data.to_dict() + measurements.append(measurements_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "categoryId": category_id, + "sizeGroupIds": size_group_ids, + "enumFields": enum_fields, + "textFields": text_fields, + "measurements": measurements, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.catalog_enum_field import CatalogEnumField + from ..models.catalog_measurement import CatalogMeasurement + from ..models.catalog_text_field import CatalogTextField + + d = dict(src_dict) + category_id = d.pop("categoryId") + + size_group_ids = cast(list[int], d.pop("sizeGroupIds")) + + enum_fields = [] + _enum_fields = d.pop("enumFields") + for enum_fields_item_data in _enum_fields: + enum_fields_item = CatalogEnumField.from_dict(enum_fields_item_data) + + enum_fields.append(enum_fields_item) + + text_fields = [] + _text_fields = d.pop("textFields") + for text_fields_item_data in _text_fields: + text_fields_item = CatalogTextField.from_dict(text_fields_item_data) + + text_fields.append(text_fields_item) + + measurements = [] + _measurements = d.pop("measurements") + for measurements_item_data in _measurements: + measurements_item = CatalogMeasurement.from_dict(measurements_item_data) + + measurements.append(measurements_item) + + catalog_category_fields = cls( + category_id=category_id, + size_group_ids=size_group_ids, + enum_fields=enum_fields, + text_fields=text_fields, + measurements=measurements, + ) + + catalog_category_fields.additional_properties = d + return catalog_category_fields + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_category_page.py b/src/controlresell/generated/models/catalog_category_page.py new file mode 100644 index 0000000..9040cb0 --- /dev/null +++ b/src/controlresell/generated/models/catalog_category_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.catalog_category import CatalogCategory + + +T = TypeVar("T", bound="CatalogCategoryPage") + + +@_attrs_define +class CatalogCategoryPage: + """ + Attributes: + data (list[CatalogCategory]): + next_cursor (None | str | Unset): + """ + + data: list[CatalogCategory] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.catalog_category import CatalogCategory + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = CatalogCategory.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + catalog_category_page = cls( + data=data, + next_cursor=next_cursor, + ) + + catalog_category_page.additional_properties = d + return catalog_category_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_enum_field.py b/src/controlresell/generated/models/catalog_enum_field.py new file mode 100644 index 0000000..e608de8 --- /dev/null +++ b/src/controlresell/generated/models/catalog_enum_field.py @@ -0,0 +1,153 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.catalog_value import CatalogValue + + +T = TypeVar("T", bound="CatalogEnumField") + + +@_attrs_define +class CatalogEnumField: + """ + Attributes: + key (str): + target (str): + values (list[CatalogValue]): + title (None | str | Unset): + multiple (bool | None | Unset): + platform (None | str | Unset): + """ + + key: str + target: str + values: list[CatalogValue] + title: None | str | Unset = UNSET + multiple: bool | None | Unset = UNSET + platform: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + key = self.key + + target = self.target + + values = [] + for values_item_data in self.values: + values_item = values_item_data.to_dict() + values.append(values_item) + + title: None | str | Unset + if isinstance(self.title, Unset): + title = UNSET + else: + title = self.title + + multiple: bool | None | Unset + if isinstance(self.multiple, Unset): + multiple = UNSET + else: + multiple = self.multiple + + platform: None | str | Unset + if isinstance(self.platform, Unset): + platform = UNSET + else: + platform = self.platform + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "key": key, + "target": target, + "values": values, + } + ) + if title is not UNSET: + field_dict["title"] = title + if multiple is not UNSET: + field_dict["multiple"] = multiple + if platform is not UNSET: + field_dict["platform"] = platform + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.catalog_value import CatalogValue + + d = dict(src_dict) + key = d.pop("key") + + target = d.pop("target") + + values = [] + _values = d.pop("values") + for values_item_data in _values: + values_item = CatalogValue.from_dict(values_item_data) + + values.append(values_item) + + def _parse_title(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + title = _parse_title(d.pop("title", UNSET)) + + def _parse_multiple(data: object) -> bool | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(bool | None | Unset, data) + + multiple = _parse_multiple(d.pop("multiple", UNSET)) + + def _parse_platform(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + platform = _parse_platform(d.pop("platform", UNSET)) + + catalog_enum_field = cls( + key=key, + target=target, + values=values, + title=title, + multiple=multiple, + platform=platform, + ) + + catalog_enum_field.additional_properties = d + return catalog_enum_field + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_measurement.py b/src/controlresell/generated/models/catalog_measurement.py new file mode 100644 index 0000000..5ba44f7 --- /dev/null +++ b/src/controlresell/generated/models/catalog_measurement.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="CatalogMeasurement") + + +@_attrs_define +class CatalogMeasurement: + """ + Attributes: + target (str): + unit (str): + required (bool): + """ + + target: str + unit: str + required: bool + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + target = self.target + + unit = self.unit + + required = self.required + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "target": target, + "unit": unit, + "required": required, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + target = d.pop("target") + + unit = d.pop("unit") + + required = d.pop("required") + + catalog_measurement = cls( + target=target, + unit=unit, + required=required, + ) + + catalog_measurement.additional_properties = d + return catalog_measurement + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_size.py b/src/controlresell/generated/models/catalog_size.py new file mode 100644 index 0000000..322f302 --- /dev/null +++ b/src/controlresell/generated/models/catalog_size.py @@ -0,0 +1,85 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="CatalogSize") + + +@_attrs_define +class CatalogSize: + """ + Attributes: + id (int): + title (str): + size_group_id (int): + size_group_title (str): + """ + + id: int + title: str + size_group_id: int + size_group_title: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + title = self.title + + size_group_id = self.size_group_id + + size_group_title = self.size_group_title + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "title": title, + "sizeGroupId": size_group_id, + "sizeGroupTitle": size_group_title, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + id = d.pop("id") + + title = d.pop("title") + + size_group_id = d.pop("sizeGroupId") + + size_group_title = d.pop("sizeGroupTitle") + + catalog_size = cls( + id=id, + title=title, + size_group_id=size_group_id, + size_group_title=size_group_title, + ) + + catalog_size.additional_properties = d + return catalog_size + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_size_page.py b/src/controlresell/generated/models/catalog_size_page.py new file mode 100644 index 0000000..0bf6757 --- /dev/null +++ b/src/controlresell/generated/models/catalog_size_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.catalog_size import CatalogSize + + +T = TypeVar("T", bound="CatalogSizePage") + + +@_attrs_define +class CatalogSizePage: + """ + Attributes: + data (list[CatalogSize]): + next_cursor (None | str | Unset): + """ + + data: list[CatalogSize] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.catalog_size import CatalogSize + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = CatalogSize.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + catalog_size_page = cls( + data=data, + next_cursor=next_cursor, + ) + + catalog_size_page.additional_properties = d + return catalog_size_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_text_field.py b/src/controlresell/generated/models/catalog_text_field.py new file mode 100644 index 0000000..489853e --- /dev/null +++ b/src/controlresell/generated/models/catalog_text_field.py @@ -0,0 +1,139 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="CatalogTextField") + + +@_attrs_define +class CatalogTextField: + """ + Attributes: + key (str): + type_ (str): + required (bool): + title (None | str | Unset): + validation (None | str | Unset): + platform (None | str | Unset): + """ + + key: str + type_: str + required: bool + title: None | str | Unset = UNSET + validation: None | str | Unset = UNSET + platform: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + key = self.key + + type_ = self.type_ + + required = self.required + + title: None | str | Unset + if isinstance(self.title, Unset): + title = UNSET + else: + title = self.title + + validation: None | str | Unset + if isinstance(self.validation, Unset): + validation = UNSET + else: + validation = self.validation + + platform: None | str | Unset + if isinstance(self.platform, Unset): + platform = UNSET + else: + platform = self.platform + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "key": key, + "type": type_, + "required": required, + } + ) + if title is not UNSET: + field_dict["title"] = title + if validation is not UNSET: + field_dict["validation"] = validation + if platform is not UNSET: + field_dict["platform"] = platform + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + key = d.pop("key") + + type_ = d.pop("type") + + required = d.pop("required") + + def _parse_title(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + title = _parse_title(d.pop("title", UNSET)) + + def _parse_validation(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + validation = _parse_validation(d.pop("validation", UNSET)) + + def _parse_platform(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + platform = _parse_platform(d.pop("platform", UNSET)) + + catalog_text_field = cls( + key=key, + type_=type_, + required=required, + title=title, + validation=validation, + platform=platform, + ) + + catalog_text_field.additional_properties = d + return catalog_text_field + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_value.py b/src/controlresell/generated/models/catalog_value.py new file mode 100644 index 0000000..c1714d9 --- /dev/null +++ b/src/controlresell/generated/models/catalog_value.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="CatalogValue") + + +@_attrs_define +class CatalogValue: + """ + Attributes: + id (int): + key (str): + title (str): + """ + + id: int + key: str + title: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + key = self.key + + title = self.title + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "key": key, + "title": title, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + id = d.pop("id") + + key = d.pop("key") + + title = d.pop("title") + + catalog_value = cls( + id=id, + key=key, + title=title, + ) + + catalog_value.additional_properties = d + return catalog_value + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/catalog_value_page.py b/src/controlresell/generated/models/catalog_value_page.py new file mode 100644 index 0000000..be6f1bd --- /dev/null +++ b/src/controlresell/generated/models/catalog_value_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.catalog_value import CatalogValue + + +T = TypeVar("T", bound="CatalogValuePage") + + +@_attrs_define +class CatalogValuePage: + """ + Attributes: + data (list[CatalogValue]): + next_cursor (None | str | Unset): + """ + + data: list[CatalogValue] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.catalog_value import CatalogValue + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = CatalogValue.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + catalog_value_page = cls( + data=data, + next_cursor=next_cursor, + ) + + catalog_value_page.additional_properties = d + return catalog_value_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/created_webhook_endpoint.py b/src/controlresell/generated/models/created_webhook_endpoint.py new file mode 100644 index 0000000..fde5b79 --- /dev/null +++ b/src/controlresell/generated/models/created_webhook_endpoint.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.webhook_endpoint import WebhookEndpoint + + +T = TypeVar("T", bound="CreatedWebhookEndpoint") + + +@_attrs_define +class CreatedWebhookEndpoint: + """ + Attributes: + endpoint (WebhookEndpoint): + secret (str): + """ + + endpoint: WebhookEndpoint + secret: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + endpoint = self.endpoint.to_dict() + + secret = self.secret + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "endpoint": endpoint, + "secret": secret, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.webhook_endpoint import WebhookEndpoint + + d = dict(src_dict) + endpoint = WebhookEndpoint.from_dict(d.pop("endpoint")) + + secret = d.pop("secret") + + created_webhook_endpoint = cls( + endpoint=endpoint, + secret=secret, + ) + + created_webhook_endpoint.additional_properties = d + return created_webhook_endpoint + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_delivery.py b/src/controlresell/generated/models/webhook_delivery.py new file mode 100644 index 0000000..71d6505 --- /dev/null +++ b/src/controlresell/generated/models/webhook_delivery.py @@ -0,0 +1,203 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast +from uuid import UUID + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookDelivery") + + +@_attrs_define +class WebhookDelivery: + """ + Attributes: + id (UUID): + event_id (UUID): + event_type (str): + status (str): + attempt (int): + created_at (datetime.datetime): + updated_at (datetime.datetime): + http_status (int | None | Unset): + error (None | str | Unset): + duration_ms (int | None | Unset): + next_attempt_at (datetime.datetime | None | Unset): + """ + + id: UUID + event_id: UUID + event_type: str + status: str + attempt: int + created_at: datetime.datetime + updated_at: datetime.datetime + http_status: int | None | Unset = UNSET + error: None | str | Unset = UNSET + duration_ms: int | None | Unset = UNSET + next_attempt_at: datetime.datetime | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = str(self.id) + + event_id = str(self.event_id) + + event_type = self.event_type + + status = self.status + + attempt = self.attempt + + created_at = self.created_at.isoformat() + + updated_at = self.updated_at.isoformat() + + http_status: int | None | Unset + if isinstance(self.http_status, Unset): + http_status = UNSET + else: + http_status = self.http_status + + error: None | str | Unset + if isinstance(self.error, Unset): + error = UNSET + else: + error = self.error + + duration_ms: int | None | Unset + if isinstance(self.duration_ms, Unset): + duration_ms = UNSET + else: + duration_ms = self.duration_ms + + next_attempt_at: None | str | Unset + if isinstance(self.next_attempt_at, Unset): + next_attempt_at = UNSET + elif isinstance(self.next_attempt_at, datetime.datetime): + next_attempt_at = self.next_attempt_at.isoformat() + else: + next_attempt_at = self.next_attempt_at + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "eventId": event_id, + "eventType": event_type, + "status": status, + "attempt": attempt, + "createdAt": created_at, + "updatedAt": updated_at, + } + ) + if http_status is not UNSET: + field_dict["httpStatus"] = http_status + if error is not UNSET: + field_dict["error"] = error + if duration_ms is not UNSET: + field_dict["durationMs"] = duration_ms + if next_attempt_at is not UNSET: + field_dict["nextAttemptAt"] = next_attempt_at + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + id = UUID(d.pop("id")) + + event_id = UUID(d.pop("eventId")) + + event_type = d.pop("eventType") + + status = d.pop("status") + + attempt = d.pop("attempt") + + created_at = datetime.datetime.fromisoformat(d.pop("createdAt")) + + updated_at = datetime.datetime.fromisoformat(d.pop("updatedAt")) + + def _parse_http_status(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + http_status = _parse_http_status(d.pop("httpStatus", UNSET)) + + def _parse_error(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + error = _parse_error(d.pop("error", UNSET)) + + def _parse_duration_ms(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + duration_ms = _parse_duration_ms(d.pop("durationMs", UNSET)) + + def _parse_next_attempt_at(data: object) -> datetime.datetime | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + next_attempt_at_type_0 = datetime.datetime.fromisoformat(data) + + return next_attempt_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None | Unset, data) + + next_attempt_at = _parse_next_attempt_at(d.pop("nextAttemptAt", UNSET)) + + webhook_delivery = cls( + id=id, + event_id=event_id, + event_type=event_type, + status=status, + attempt=attempt, + created_at=created_at, + updated_at=updated_at, + http_status=http_status, + error=error, + duration_ms=duration_ms, + next_attempt_at=next_attempt_at, + ) + + webhook_delivery.additional_properties = d + return webhook_delivery + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_delivery_page.py b/src/controlresell/generated/models/webhook_delivery_page.py new file mode 100644 index 0000000..839645b --- /dev/null +++ b/src/controlresell/generated/models/webhook_delivery_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.webhook_delivery import WebhookDelivery + + +T = TypeVar("T", bound="WebhookDeliveryPage") + + +@_attrs_define +class WebhookDeliveryPage: + """ + Attributes: + data (list[WebhookDelivery]): + next_cursor (None | str | Unset): + """ + + data: list[WebhookDelivery] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.webhook_delivery import WebhookDelivery + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = WebhookDelivery.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + webhook_delivery_page = cls( + data=data, + next_cursor=next_cursor, + ) + + webhook_delivery_page.additional_properties = d + return webhook_delivery_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_endpoint.py b/src/controlresell/generated/models/webhook_endpoint.py new file mode 100644 index 0000000..814407b --- /dev/null +++ b/src/controlresell/generated/models/webhook_endpoint.py @@ -0,0 +1,191 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast +from uuid import UUID + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookEndpoint") + + +@_attrs_define +class WebhookEndpoint: + """ + Attributes: + id (UUID): + url (str): + event_types (list[str]): + payload_mode (str): + status (str): + api_version (str): + created_at (datetime.datetime): + updated_at (datetime.datetime): + description (None | str | Unset): + disabled_reason (None | str | Unset): + last_success_at (datetime.datetime | None | Unset): + """ + + id: UUID + url: str + event_types: list[str] + payload_mode: str + status: str + api_version: str + created_at: datetime.datetime + updated_at: datetime.datetime + description: None | str | Unset = UNSET + disabled_reason: None | str | Unset = UNSET + last_success_at: datetime.datetime | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = str(self.id) + + url = self.url + + event_types = self.event_types + + payload_mode = self.payload_mode + + status = self.status + + api_version = self.api_version + + created_at = self.created_at.isoformat() + + updated_at = self.updated_at.isoformat() + + description: None | str | Unset + if isinstance(self.description, Unset): + description = UNSET + else: + description = self.description + + disabled_reason: None | str | Unset + if isinstance(self.disabled_reason, Unset): + disabled_reason = UNSET + else: + disabled_reason = self.disabled_reason + + last_success_at: None | str | Unset + if isinstance(self.last_success_at, Unset): + last_success_at = UNSET + elif isinstance(self.last_success_at, datetime.datetime): + last_success_at = self.last_success_at.isoformat() + else: + last_success_at = self.last_success_at + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "url": url, + "eventTypes": event_types, + "payloadMode": payload_mode, + "status": status, + "apiVersion": api_version, + "createdAt": created_at, + "updatedAt": updated_at, + } + ) + if description is not UNSET: + field_dict["description"] = description + if disabled_reason is not UNSET: + field_dict["disabledReason"] = disabled_reason + if last_success_at is not UNSET: + field_dict["lastSuccessAt"] = last_success_at + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + id = UUID(d.pop("id")) + + url = d.pop("url") + + event_types = cast(list[str], d.pop("eventTypes")) + + payload_mode = d.pop("payloadMode") + + status = d.pop("status") + + api_version = d.pop("apiVersion") + + created_at = datetime.datetime.fromisoformat(d.pop("createdAt")) + + updated_at = datetime.datetime.fromisoformat(d.pop("updatedAt")) + + def _parse_description(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + description = _parse_description(d.pop("description", UNSET)) + + def _parse_disabled_reason(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + disabled_reason = _parse_disabled_reason(d.pop("disabledReason", UNSET)) + + def _parse_last_success_at(data: object) -> datetime.datetime | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + last_success_at_type_0 = datetime.datetime.fromisoformat(data) + + return last_success_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None | Unset, data) + + last_success_at = _parse_last_success_at(d.pop("lastSuccessAt", UNSET)) + + webhook_endpoint = cls( + id=id, + url=url, + event_types=event_types, + payload_mode=payload_mode, + status=status, + api_version=api_version, + created_at=created_at, + updated_at=updated_at, + description=description, + disabled_reason=disabled_reason, + last_success_at=last_success_at, + ) + + webhook_endpoint.additional_properties = d + return webhook_endpoint + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_endpoint_create_request.py b/src/controlresell/generated/models/webhook_endpoint_create_request.py new file mode 100644 index 0000000..28b9282 --- /dev/null +++ b/src/controlresell/generated/models/webhook_endpoint_create_request.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookEndpointCreateRequest") + + +@_attrs_define +class WebhookEndpointCreateRequest: + """ + Attributes: + url (str): + event_types (list[str]): + description (None | str | Unset): + payload_mode (None | str | Unset): + """ + + url: str + event_types: list[str] + description: None | str | Unset = UNSET + payload_mode: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + url = self.url + + event_types = self.event_types + + description: None | str | Unset + if isinstance(self.description, Unset): + description = UNSET + else: + description = self.description + + payload_mode: None | str | Unset + if isinstance(self.payload_mode, Unset): + payload_mode = UNSET + else: + payload_mode = self.payload_mode + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "url": url, + "eventTypes": event_types, + } + ) + if description is not UNSET: + field_dict["description"] = description + if payload_mode is not UNSET: + field_dict["payloadMode"] = payload_mode + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + url = d.pop("url") + + event_types = cast(list[str], d.pop("eventTypes")) + + def _parse_description(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + description = _parse_description(d.pop("description", UNSET)) + + def _parse_payload_mode(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + payload_mode = _parse_payload_mode(d.pop("payloadMode", UNSET)) + + webhook_endpoint_create_request = cls( + url=url, + event_types=event_types, + description=description, + payload_mode=payload_mode, + ) + + webhook_endpoint_create_request.additional_properties = d + return webhook_endpoint_create_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_endpoint_page.py b/src/controlresell/generated/models/webhook_endpoint_page.py new file mode 100644 index 0000000..de8c47f --- /dev/null +++ b/src/controlresell/generated/models/webhook_endpoint_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.webhook_endpoint import WebhookEndpoint + + +T = TypeVar("T", bound="WebhookEndpointPage") + + +@_attrs_define +class WebhookEndpointPage: + """ + Attributes: + data (list[WebhookEndpoint]): + next_cursor (None | str | Unset): + """ + + data: list[WebhookEndpoint] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.webhook_endpoint import WebhookEndpoint + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = WebhookEndpoint.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + webhook_endpoint_page = cls( + data=data, + next_cursor=next_cursor, + ) + + webhook_endpoint_page.additional_properties = d + return webhook_endpoint_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_endpoint_update_request.py b/src/controlresell/generated/models/webhook_endpoint_update_request.py new file mode 100644 index 0000000..217c1f7 --- /dev/null +++ b/src/controlresell/generated/models/webhook_endpoint_update_request.py @@ -0,0 +1,164 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookEndpointUpdateRequest") + + +@_attrs_define +class WebhookEndpointUpdateRequest: + """ + Attributes: + url (None | str | Unset): + description (None | str | Unset): + event_types (list[str] | None | Unset): + payload_mode (None | str | Unset): + status (None | str | Unset): + """ + + url: None | str | Unset = UNSET + description: None | str | Unset = UNSET + event_types: list[str] | None | Unset = UNSET + payload_mode: None | str | Unset = UNSET + status: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + url: None | str | Unset + if isinstance(self.url, Unset): + url = UNSET + else: + url = self.url + + description: None | str | Unset + if isinstance(self.description, Unset): + description = UNSET + else: + description = self.description + + event_types: list[str] | None | Unset + if isinstance(self.event_types, Unset): + event_types = UNSET + elif isinstance(self.event_types, list): + event_types = self.event_types + + else: + event_types = self.event_types + + payload_mode: None | str | Unset + if isinstance(self.payload_mode, Unset): + payload_mode = UNSET + else: + payload_mode = self.payload_mode + + status: None | str | Unset + if isinstance(self.status, Unset): + status = UNSET + else: + status = self.status + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if url is not UNSET: + field_dict["url"] = url + if description is not UNSET: + field_dict["description"] = description + if event_types is not UNSET: + field_dict["eventTypes"] = event_types + if payload_mode is not UNSET: + field_dict["payloadMode"] = payload_mode + if status is not UNSET: + field_dict["status"] = status + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + + def _parse_url(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + url = _parse_url(d.pop("url", UNSET)) + + def _parse_description(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + description = _parse_description(d.pop("description", UNSET)) + + def _parse_event_types(data: object) -> list[str] | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, list): + raise TypeError() + event_types_type_0 = cast(list[str], data) + + return event_types_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[str] | None | Unset, data) + + event_types = _parse_event_types(d.pop("eventTypes", UNSET)) + + def _parse_payload_mode(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + payload_mode = _parse_payload_mode(d.pop("payloadMode", UNSET)) + + def _parse_status(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + status = _parse_status(d.pop("status", UNSET)) + + webhook_endpoint_update_request = cls( + url=url, + description=description, + event_types=event_types, + payload_mode=payload_mode, + status=status, + ) + + webhook_endpoint_update_request.additional_properties = d + return webhook_endpoint_update_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_event.py b/src/controlresell/generated/models/webhook_event.py new file mode 100644 index 0000000..345b8db --- /dev/null +++ b/src/controlresell/generated/models/webhook_event.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar +from uuid import UUID + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.webhook_event_data import WebhookEventData + + +T = TypeVar("T", bound="WebhookEvent") + + +@_attrs_define +class WebhookEvent: + """ + Attributes: + id (UUID): + type_ (str): + created_at (datetime.datetime): + api_version (str): + seller_id (int): + data (WebhookEventData): + """ + + id: UUID + type_: str + created_at: datetime.datetime + api_version: str + seller_id: int + data: WebhookEventData + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = str(self.id) + + type_ = self.type_ + + created_at = self.created_at.isoformat() + + api_version = self.api_version + + seller_id = self.seller_id + + data = self.data.to_dict() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "type": type_, + "createdAt": created_at, + "apiVersion": api_version, + "sellerId": seller_id, + "data": data, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.webhook_event_data import WebhookEventData + + d = dict(src_dict) + id = UUID(d.pop("id")) + + type_ = d.pop("type") + + created_at = datetime.datetime.fromisoformat(d.pop("createdAt")) + + api_version = d.pop("apiVersion") + + seller_id = d.pop("sellerId") + + data = WebhookEventData.from_dict(d.pop("data")) + + webhook_event = cls( + id=id, + type_=type_, + created_at=created_at, + api_version=api_version, + seller_id=seller_id, + data=data, + ) + + webhook_event.additional_properties = d + return webhook_event + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_event_data.py b/src/controlresell/generated/models/webhook_event_data.py new file mode 100644 index 0000000..35c2bef --- /dev/null +++ b/src/controlresell/generated/models/webhook_event_data.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WebhookEventData") + + +@_attrs_define +class WebhookEventData: + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + webhook_event_data = cls() + + webhook_event_data.additional_properties = d + return webhook_event_data + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_event_page.py b/src/controlresell/generated/models/webhook_event_page.py new file mode 100644 index 0000000..957ce75 --- /dev/null +++ b/src/controlresell/generated/models/webhook_event_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.webhook_event import WebhookEvent + + +T = TypeVar("T", bound="WebhookEventPage") + + +@_attrs_define +class WebhookEventPage: + """ + Attributes: + data (list[WebhookEvent]): + next_cursor (None | str | Unset): + """ + + data: list[WebhookEvent] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.webhook_event import WebhookEvent + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = WebhookEvent.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + webhook_event_page = cls( + data=data, + next_cursor=next_cursor, + ) + + webhook_event_page.additional_properties = d + return webhook_event_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_event_type.py b/src/controlresell/generated/models/webhook_event_type.py new file mode 100644 index 0000000..4e544aa --- /dev/null +++ b/src/controlresell/generated/models/webhook_event_type.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookEventType") + + +@_attrs_define +class WebhookEventType: + """ + Attributes: + type_ (str): + scope (None | str | Unset): + """ + + type_: str + scope: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + type_ = self.type_ + + scope: None | str | Unset + if isinstance(self.scope, Unset): + scope = UNSET + else: + scope = self.scope + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "type": type_, + } + ) + if scope is not UNSET: + field_dict["scope"] = scope + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + type_ = d.pop("type") + + def _parse_scope(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + scope = _parse_scope(d.pop("scope", UNSET)) + + webhook_event_type = cls( + type_=type_, + scope=scope, + ) + + webhook_event_type.additional_properties = d + return webhook_event_type + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_event_type_list.py b/src/controlresell/generated/models/webhook_event_type_list.py new file mode 100644 index 0000000..62fe6cd --- /dev/null +++ b/src/controlresell/generated/models/webhook_event_type_list.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.webhook_event_type import WebhookEventType + + +T = TypeVar("T", bound="WebhookEventTypeList") + + +@_attrs_define +class WebhookEventTypeList: + """ + Attributes: + data (list[WebhookEventType]): + """ + + data: list[WebhookEventType] + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.webhook_event_type import WebhookEventType + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = WebhookEventType.from_dict(data_item_data) + + data.append(data_item) + + webhook_event_type_list = cls( + data=data, + ) + + webhook_event_type_list.additional_properties = d + return webhook_event_type_list + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_recover_request.py b/src/controlresell/generated/models/webhook_recover_request.py new file mode 100644 index 0000000..34e0425 --- /dev/null +++ b/src/controlresell/generated/models/webhook_recover_request.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WebhookRecoverRequest") + + +@_attrs_define +class WebhookRecoverRequest: + """ + Attributes: + since (datetime.datetime): + """ + + since: datetime.datetime + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + since = self.since.isoformat() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "since": since, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + since = datetime.datetime.fromisoformat(d.pop("since")) + + webhook_recover_request = cls( + since=since, + ) + + webhook_recover_request.additional_properties = d + return webhook_recover_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_recovery.py b/src/controlresell/generated/models/webhook_recovery.py new file mode 100644 index 0000000..8da791e --- /dev/null +++ b/src/controlresell/generated/models/webhook_recovery.py @@ -0,0 +1,69 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WebhookRecovery") + + +@_attrs_define +class WebhookRecovery: + """ + Attributes: + count (int): + has_more (bool): + """ + + count: int + has_more: bool + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + count = self.count + + has_more = self.has_more + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "count": count, + "hasMore": has_more, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + count = d.pop("count") + + has_more = d.pop("hasMore") + + webhook_recovery = cls( + count=count, + has_more=has_more, + ) + + webhook_recovery.additional_properties = d + return webhook_recovery + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_secret.py b/src/controlresell/generated/models/webhook_secret.py new file mode 100644 index 0000000..9590af1 --- /dev/null +++ b/src/controlresell/generated/models/webhook_secret.py @@ -0,0 +1,100 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookSecret") + + +@_attrs_define +class WebhookSecret: + """ + Attributes: + secret (str): + previous_secret_expires_at (datetime.datetime | None | Unset): + """ + + secret: str + previous_secret_expires_at: datetime.datetime | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + secret = self.secret + + previous_secret_expires_at: None | str | Unset + if isinstance(self.previous_secret_expires_at, Unset): + previous_secret_expires_at = UNSET + elif isinstance(self.previous_secret_expires_at, datetime.datetime): + previous_secret_expires_at = self.previous_secret_expires_at.isoformat() + else: + previous_secret_expires_at = self.previous_secret_expires_at + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "secret": secret, + } + ) + if previous_secret_expires_at is not UNSET: + field_dict["previousSecretExpiresAt"] = previous_secret_expires_at + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + secret = d.pop("secret") + + def _parse_previous_secret_expires_at( + data: object, + ) -> datetime.datetime | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + previous_secret_expires_at_type_0 = datetime.datetime.fromisoformat( + data + ) + + return previous_secret_expires_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None | Unset, data) + + previous_secret_expires_at = _parse_previous_secret_expires_at( + d.pop("previousSecretExpiresAt", UNSET) + ) + + webhook_secret = cls( + secret=secret, + previous_secret_expires_at=previous_secret_expires_at, + ) + + webhook_secret.additional_properties = d + return webhook_secret + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_secret_rotate_request.py b/src/controlresell/generated/models/webhook_secret_rotate_request.py new file mode 100644 index 0000000..269de67 --- /dev/null +++ b/src/controlresell/generated/models/webhook_secret_rotate_request.py @@ -0,0 +1,73 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookSecretRotateRequest") + + +@_attrs_define +class WebhookSecretRotateRequest: + """ + Attributes: + expires_in_hours (int | None | Unset): + """ + + expires_in_hours: int | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + expires_in_hours: int | None | Unset + if isinstance(self.expires_in_hours, Unset): + expires_in_hours = UNSET + else: + expires_in_hours = self.expires_in_hours + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if expires_in_hours is not UNSET: + field_dict["expiresInHours"] = expires_in_hours + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + + def _parse_expires_in_hours(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + expires_in_hours = _parse_expires_in_hours(d.pop("expiresInHours", UNSET)) + + webhook_secret_rotate_request = cls( + expires_in_hours=expires_in_hours, + ) + + webhook_secret_rotate_request.additional_properties = d + return webhook_secret_rotate_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/webhook_test_result.py b/src/controlresell/generated/models/webhook_test_result.py new file mode 100644 index 0000000..64b0539 --- /dev/null +++ b/src/controlresell/generated/models/webhook_test_result.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WebhookTestResult") + + +@_attrs_define +class WebhookTestResult: + """ + Attributes: + success (bool): + duration_ms (int): + status_code (int | None | Unset): + error (None | str | Unset): + """ + + success: bool + duration_ms: int + status_code: int | None | Unset = UNSET + error: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + success = self.success + + duration_ms = self.duration_ms + + status_code: int | None | Unset + if isinstance(self.status_code, Unset): + status_code = UNSET + else: + status_code = self.status_code + + error: None | str | Unset + if isinstance(self.error, Unset): + error = UNSET + else: + error = self.error + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "success": success, + "durationMs": duration_ms, + } + ) + if status_code is not UNSET: + field_dict["statusCode"] = status_code + if error is not UNSET: + field_dict["error"] = error + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + d = dict(src_dict) + success = d.pop("success") + + duration_ms = d.pop("durationMs") + + def _parse_status_code(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + status_code = _parse_status_code(d.pop("statusCode", UNSET)) + + def _parse_error(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + error = _parse_error(d.pop("error", UNSET)) + + webhook_test_result = cls( + success=success, + duration_ms=duration_ms, + status_code=status_code, + error=error, + ) + + webhook_test_result.additional_properties = d + return webhook_test_result + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/tests/test_client.py b/tests/test_client.py index 1ca691f..b677161 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -368,6 +368,34 @@ def test_customers_get_reads_one_customer(): assert requests[0].url.path == f"/api/public/v1/customers/{ACCOUNT}" +def test_catalogs_iter_brands_follows_the_cursor_with_the_same_query(): + seen = [] + + def handler(request): + seen.append(request.url) + if request.url.params.get("cursor"): + return reply({"data": [{"id": 2, "name": "Nikon", "custom": True}], "nextCursor": None}) + return reply({"data": [{"id": 1, "name": "Nike", "custom": False}], "nextCursor": "c2"}) + + _, sdk = client(handler) + assert [b.name for b in sdk.catalogs.iter_brands(q="nik")] == ["Nike", "Nikon"] + assert [u.path for u in seen] == ["/api/public/v1/catalogs/brands"] * 2 + assert [u.params["q"] for u in seen] == ["nik", "nik"] and seen[1].params["cursor"] == "c2" + + +def test_catalogs_colors_send_the_category_and_read_the_values(): + requests, sdk = client(lambda r: reply({"data": [{"id": 3, "key": "red", "title": "Red"}], "nextCursor": None})) + assert sdk.catalogs.colors(category_id=12).data[0].title == "Red" + assert requests[0].url.path == "/api/public/v1/catalogs/colors" and requests[0].url.params["categoryId"] == "12" + + +def test_catalogs_category_fields_reads_the_fields_of_one_category(): + body = {"categoryId": 12, "sizeGroupIds": [1], "enumFields": [], "textFields": [], "measurements": []} + requests, sdk = client(lambda r: reply(body)) + assert sdk.catalogs.category_fields(12).category_id == 12 + assert requests[0].url.path == "/api/public/v1/catalogs/categories/12/fields" + + def test_conversations_messages_and_list_send_the_from_and_to_window(): import datetime @@ -378,3 +406,78 @@ def test_conversations_messages_and_list_send_the_from_and_to_window(): first, second = (r.url.params for r in requests) assert first["from"] == "2026-10-01T00:00:00+00:00" and first["to"] == "2026-10-02T00:00:00+00:00" assert second["from"] == "2026-10-01T00:00:00+00:00" and "to" not in second + + +ENDPOINT_ID = "0b6f3c1e-8d43-4a4c-9a55-7f1f2c3d4e5f" +ENDPOINT = { + "id": ENDPOINT_ID, "url": "https://example.com/hook", "description": None, "eventTypes": ["item.sold"], + "payloadMode": "light", "status": "enabled", "apiVersion": "v1", "createdAt": "2026-10-24T00:00:00Z", + "updatedAt": "2026-10-24T00:00:00Z", +} + + +def test_webhooks_create_endpoint_posts_with_a_key_and_returns_the_secret(): + from controlresell.generated.models import WebhookEndpointCreateRequest + + requests, sdk = client(lambda r: reply({"endpoint": ENDPOINT, "secret": "whsec_abc"}, 201)) + created = sdk.webhooks.create_endpoint(WebhookEndpointCreateRequest(url="https://example.com/hook", event_types=["item.sold"])) + assert created.secret == "whsec_abc" and created.endpoint.status == "enabled" + request = requests[0] + assert request.method == "POST" and request.url.path == "/api/public/v1/webhook-endpoints" + assert request.headers[IDEMPOTENCY_KEY_HEADER] and json.loads(request.content)["eventTypes"] == ["item.sold"] + + +def test_webhooks_update_endpoint_sends_an_explicit_null_to_clear_the_description(): + from controlresell.generated.models import WebhookEndpointUpdateRequest + + requests, sdk = client(lambda r: reply(ENDPOINT)) + sdk.webhooks.update_endpoint(ENDPOINT_ID, WebhookEndpointUpdateRequest(description=None)) + assert requests[0].method == "PATCH" and json.loads(requests[0].content) == {"description": None} + + +def test_webhooks_iter_events_follows_the_cursor_with_the_same_types_and_reads_any_data(): + def handler(request): + if "cursor" not in request.url.params: + return reply({"data": [{"id": "0192f3c1-0000-7000-8000-000000000001", "type": "item.sold", + "createdAt": "2026-10-24T00:00:00Z", "apiVersion": "v1", "sellerId": 7, + "data": {"itemId": 42, "source": "order", "object": None}}], "nextCursor": "c2"}) + return reply({"data": [{"id": "0192f3c1-0000-7000-8000-000000000002", "type": "order.created", + "createdAt": "2026-10-24T00:01:00Z", "apiVersion": "v1", "sellerId": 7, + "data": {"orderId": "o1", "items": [1, 2]}}], "nextCursor": None}) + + requests, sdk = client(handler) + events = list(sdk.webhooks.iter_events(types=["item.sold", "order.created"])) + assert [e.type_ for e in events] == ["item.sold", "order.created"] + assert events[0].data["itemId"] == 42 and events[1].data["items"] == [1, 2] + assert [r.url.params["type"] for r in requests] == ["item.sold,order.created"] * 2 + assert requests[1].url.params["cursor"] == "c2" + + +def test_webhooks_deliveries_send_the_filters_and_retry_posts_to_the_delivery(): + delivery = {"id": "11111111-2222-3333-4444-555555555555", "eventId": "11111111-2222-3333-4444-666666666666", + "eventType": "item.sold", "status": "failed", "attempt": 3, "createdAt": "2026-10-24T00:00:00Z", + "updatedAt": "2026-10-24T00:00:00Z"} + + def handler(request): + if request.method == "GET": + return reply({"data": [delivery], "nextCursor": None}) + return reply(delivery, 202) + + requests, sdk = client(handler) + assert sdk.webhooks.deliveries(ENDPOINT_ID, status="failed").data[0].attempt == 3 + sdk.webhooks.retry_delivery(ENDPOINT_ID, delivery["id"]) + assert requests[0].url.path == f"/api/public/v1/webhook-endpoints/{ENDPOINT_ID}/deliveries" + assert requests[0].url.params["status"] == "failed" + assert requests[1].url.path == f"/api/public/v1/webhook-endpoints/{ENDPOINT_ID}/deliveries/{delivery['id']}/retry" + + +def test_webhooks_rotate_secret_sends_the_overlap_and_delete_resolves_on_204(): + def handler(request): + if request.method == "DELETE": + return httpx.Response(204) + return reply({"secret": "whsec_new", "previousSecretExpiresAt": "2026-10-25T00:00:00Z"}) + + requests, sdk = client(handler) + assert sdk.webhooks.rotate_secret(ENDPOINT_ID, expires_in_hours=0).secret == "whsec_new" + assert json.loads(requests[0].content) == {"expiresInHours": 0} + assert sdk.webhooks.delete_endpoint(ENDPOINT_ID) is None From 745ba8903e3e1c5307a06f156bb5dab1ca46166a Mon Sep 17 00:00:00 2001 From: Nathan Fallet Date: Sat, 24 Oct 2026 02:32:46 +0100 Subject: [PATCH 2/4] docs: say what the category_id filter of a catalog list keeps --- src/controlresell/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controlresell/client.py b/src/controlresell/client.py index f7b644d..4bbedb4 100644 --- a/src/controlresell/client.py +++ b/src/controlresell/client.py @@ -487,7 +487,7 @@ def iter( class _Catalogs: """The catalog an item is written with: categories, brands, sizes, colors... (needs the ``items:read`` scope). - Every ``category_id`` keeps what applies to one category. + The ``category_id`` filter of a list keeps only the values that apply to that category. """ def __init__(self, sdk: ControlResell) -> None: From 00bbfb3a5d299c645e4bc4f52c30818a3adbbeb4 Mon Sep 17 00:00:00 2001 From: NathanFallet Date: Sat, 24 Oct 2026 04:12:46 +0100 Subject: [PATCH 3/4] chore: regenerate from the production document --- .spec-sha256 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.spec-sha256 b/.spec-sha256 index 35c0bf5..d2e7f25 100644 --- a/.spec-sha256 +++ b/.spec-sha256 @@ -1 +1 @@ -f10e5e1224ad85ecad716478692839f8420090b5fa2f1dfcc9b0d287634172a3 +ebb5be8281f5e74b3760b545d2a81f0c3fda8670adf67af137a4979081abc7d8 From 80898c8420095b3c83ecaa29c5626645ff64ebba Mon Sep 17 00:00:00 2001 From: NathanFallet Date: Sat, 24 Oct 2026 04:39:45 +0100 Subject: [PATCH 4/4] feat: regenerate with the favorites routes and the conversation filters, and expose them --- .spec-sha256 | 2 +- README.md | 4 + src/controlresell/client.py | 89 ++++- .../api/conversations/list_conversations.py | 73 +++- .../generated/api/favorites/__init__.py | 1 + .../generated/api/favorites/list_favorites.py | 311 ++++++++++++++++++ .../api/favorites/list_item_favorites.py | 294 +++++++++++++++++ .../generated/models/__init__.py | 6 + .../generated/models/conversation.py | 20 ++ .../generated/models/favorite.py | 207 ++++++++++++ .../generated/models/favorite_item.py | 91 +++++ .../generated/models/favorite_page.py | 97 ++++++ tests/test_client.py | 46 +++ 13 files changed, 1235 insertions(+), 6 deletions(-) create mode 100644 src/controlresell/generated/api/favorites/__init__.py create mode 100644 src/controlresell/generated/api/favorites/list_favorites.py create mode 100644 src/controlresell/generated/api/favorites/list_item_favorites.py create mode 100644 src/controlresell/generated/models/favorite.py create mode 100644 src/controlresell/generated/models/favorite_item.py create mode 100644 src/controlresell/generated/models/favorite_page.py diff --git a/.spec-sha256 b/.spec-sha256 index d2e7f25..3c42680 100644 --- a/.spec-sha256 +++ b/.spec-sha256 @@ -1 +1 @@ -ebb5be8281f5e74b3760b545d2a81f0c3fda8670adf67af137a4979081abc7d8 +d95f1962bb73a3e9792c2de01bd086edce7d3c1371ece42f7c4f12032cd29e17 diff --git a/README.md b/README.md index 2230ba9..b63adfb 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ for order in client.orders.iter(bucket="to_send"): # needs the orders:read scop for brand in client.catalogs.iter_brands(q="nik"): # the identifiers an item is written with (items:read): categories, category, category_fields, brands, sizes, colors, conditions, package_sizes, materials print(brand.id, brand.name) +for favorite in client.favorites.iter(item_id=42): # the buyers who favorited a listing (items:read); also favorites.iter_item(42), list, list_item + print(favorite.buyer_id) +client.conversations.list(buyer_id="", offer_status="PENDING") # buyer_id, item_id and offer_status filter the conversations + # Writes (API key with `items:write` / `conversations:write`); `idempotency_key=` chooses the key. from controlresell.generated.models import ItemCreateRequest, ItemUpdateRequest, PublishRequest, SendMessageRequest diff --git a/src/controlresell/client.py b/src/controlresell/client.py index 4bbedb4..d920250 100644 --- a/src/controlresell/client.py +++ b/src/controlresell/client.py @@ -45,6 +45,7 @@ list_catalog_sizes, ) from .generated.api.customers import get_customer, list_customers +from .generated.api.favorites import list_favorites, list_item_favorites from .generated.api.webhooks import ( create_webhook_endpoint, delete_webhook_endpoint, @@ -80,6 +81,8 @@ CreatedWebhookEndpoint, Customer, CustomerPage, + Favorite, + FavoritePage, Item, ItemCreateRequest, ItemPage, @@ -163,6 +166,7 @@ def __init__( self.conversations = _Conversations(self) self.orders = _Orders(self) self.customers = _Customers(self) + self.favorites = _Favorites(self) self.catalogs = _Catalogs(self) self.webhooks = _Webhooks(self) @@ -309,15 +313,30 @@ def list( account_id: UUID | str | None = None, from_: datetime.datetime | None = None, to: datetime.datetime | None = None, + buyer_id: str | None = None, + item_id: int | None = None, + offer_status: str | None = None, ) -> ConversationPage: """One page of the conversations with buyers. ``from_`` (inclusive) and ``to`` (exclusive) bound the last message (a naive datetime is read as UTC). + ``buyer_id`` keeps the conversations with one buyer, ``item_id`` those about one item, ``offer_status`` + those with an offer at this status (``PENDING``, ``ACCEPTED``, ``REJECTED`` or ``CANCELED``). """ account = UUID(str(account_id)) if account_id is not None else None return self._sdk._call( # noqa: SLF001 list_conversations, - **_query(limit=limit, cursor=cursor, unread=unread, account_id=account, from_=_utc(from_), to=_utc(to)), + **_query( + limit=limit, + cursor=cursor, + unread=unread, + account_id=account, + from_=_utc(from_), + to=_utc(to), + buyer_id=buyer_id, + item_id=item_id, + offer_status=offer_status, + ), ) def get(self, id: UUID | str) -> Conversation: @@ -484,6 +503,74 @@ def iter( return paginate(lambda cursor: self.list(limit=limit, cursor=cursor, account_id=account_id, from_=from_, to=to)) +class _Favorites: + """The buyers who put the seller's listings in their favorites (needs the ``items:read`` scope).""" + + def __init__(self, sdk: ControlResell) -> None: + self._sdk = sdk + + def list( + self, + *, + limit: int | None = None, + cursor: str | None = None, + account_id: UUID | str | None = None, + item_id: int | None = None, + from_: datetime.datetime | None = None, + to: datetime.datetime | None = None, + ) -> FavoritePage: + """One page of favorites, the most recent first. + + ``from_`` is inclusive and ``to`` exclusive, on the date of the favorite (a naive datetime is read as UTC). + """ + account = UUID(str(account_id)) if account_id is not None else None + return self._sdk._call( # noqa: SLF001 + list_favorites, + **_query(limit=limit, cursor=cursor, account_id=account, item_id=item_id, from_=_utc(from_), to=_utc(to)), + ) + + def iter( + self, + *, + limit: int | None = None, + account_id: UUID | str | None = None, + item_id: int | None = None, + from_: datetime.datetime | None = None, + to: datetime.datetime | None = None, + ) -> Iterator[Favorite]: + """Every favorite, page after page, with the same filters.""" + return paginate( + lambda cursor: self.list( + limit=limit, cursor=cursor, account_id=account_id, item_id=item_id, from_=from_, to=to + ) + ) + + def list_item( + self, + id: int, + *, + limit: int | None = None, + cursor: str | None = None, + from_: datetime.datetime | None = None, + to: datetime.datetime | None = None, + ) -> FavoritePage: + """One page of the favorites of an item, on every account it is listed on, the most recent first.""" + return self._sdk._call( # noqa: SLF001 + list_item_favorites, id=id, **_query(limit=limit, cursor=cursor, from_=_utc(from_), to=_utc(to)) + ) + + def iter_item( + self, + id: int, + *, + limit: int | None = None, + from_: datetime.datetime | None = None, + to: datetime.datetime | None = None, + ) -> Iterator[Favorite]: + """Every favorite of an item, page after page, with the same period.""" + return paginate(lambda cursor: self.list_item(id, limit=limit, cursor=cursor, from_=from_, to=to)) + + class _Catalogs: """The catalog an item is written with: categories, brands, sizes, colors... (needs the ``items:read`` scope). diff --git a/src/controlresell/generated/api/conversations/list_conversations.py b/src/controlresell/generated/api/conversations/list_conversations.py index fc237ab..7514242 100644 --- a/src/controlresell/generated/api/conversations/list_conversations.py +++ b/src/controlresell/generated/api/conversations/list_conversations.py @@ -19,6 +19,9 @@ def _get_kwargs( account_id: UUID | Unset = UNSET, from_: datetime.datetime | Unset = UNSET, to: datetime.datetime | Unset = UNSET, + buyer_id: str | Unset = UNSET, + item_id: int | Unset = UNSET, + offer_status: str | Unset = UNSET, ) -> dict[str, Any]: params: dict[str, Any] = {} @@ -44,6 +47,12 @@ def _get_kwargs( json_to = to.isoformat() params["to"] = json_to + params["buyerId"] = buyer_id + + params["itemId"] = item_id + + params["offerStatus"] = offer_status + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} _kwargs: dict[str, Any] = { @@ -118,6 +127,9 @@ def sync_detailed( account_id: UUID | Unset = UNSET, from_: datetime.datetime | Unset = UNSET, to: datetime.datetime | Unset = UNSET, + buyer_id: str | Unset = UNSET, + item_id: int | Unset = UNSET, + offer_status: str | Unset = UNSET, ) -> Response[ConversationPage | ErrorResponse]: """List the seller's conversations @@ -126,7 +138,12 @@ def sync_detailed( the first page to see it. Pass the `nextCursor` of a page as `cursor` with the same filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to a period of the last message: `from` is inclusive, `to` exclusive, and the period is read page by page like the - whole list. Requires `conversations:read`. + whole list. `buyerId`, `itemId` and `offerStatus` combine with the other filters (AND): `buyerId` is + the buyer's identifier on the marketplace (a conversation's `buyerId`); `itemId` keeps the + conversations about the item, through their transactions on the marketplace (a conversation the + marketplace ties to no listing of the item is not found); `offerStatus` keeps those with at least + one offer currently at that status, and with `itemId` that same offer is on the item. An `itemId` + that is not one of the seller's items answers an empty page. Requires `conversations:read`. Args: limit (int | Unset): Default: 50. @@ -135,6 +152,9 @@ def sync_detailed( account_id (UUID | Unset): from_ (datetime.datetime | Unset): to (datetime.datetime | Unset): + buyer_id (str | Unset): + item_id (int | Unset): + offer_status (str | Unset): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -151,6 +171,9 @@ def sync_detailed( account_id=account_id, from_=from_, to=to, + buyer_id=buyer_id, + item_id=item_id, + offer_status=offer_status, ) response = client.get_httpx_client().request( @@ -169,6 +192,9 @@ def sync( account_id: UUID | Unset = UNSET, from_: datetime.datetime | Unset = UNSET, to: datetime.datetime | Unset = UNSET, + buyer_id: str | Unset = UNSET, + item_id: int | Unset = UNSET, + offer_status: str | Unset = UNSET, ) -> ConversationPage | ErrorResponse | None: """List the seller's conversations @@ -177,7 +203,12 @@ def sync( the first page to see it. Pass the `nextCursor` of a page as `cursor` with the same filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to a period of the last message: `from` is inclusive, `to` exclusive, and the period is read page by page like the - whole list. Requires `conversations:read`. + whole list. `buyerId`, `itemId` and `offerStatus` combine with the other filters (AND): `buyerId` is + the buyer's identifier on the marketplace (a conversation's `buyerId`); `itemId` keeps the + conversations about the item, through their transactions on the marketplace (a conversation the + marketplace ties to no listing of the item is not found); `offerStatus` keeps those with at least + one offer currently at that status, and with `itemId` that same offer is on the item. An `itemId` + that is not one of the seller's items answers an empty page. Requires `conversations:read`. Args: limit (int | Unset): Default: 50. @@ -186,6 +217,9 @@ def sync( account_id (UUID | Unset): from_ (datetime.datetime | Unset): to (datetime.datetime | Unset): + buyer_id (str | Unset): + item_id (int | Unset): + offer_status (str | Unset): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -203,6 +237,9 @@ def sync( account_id=account_id, from_=from_, to=to, + buyer_id=buyer_id, + item_id=item_id, + offer_status=offer_status, ).parsed @@ -215,6 +252,9 @@ async def asyncio_detailed( account_id: UUID | Unset = UNSET, from_: datetime.datetime | Unset = UNSET, to: datetime.datetime | Unset = UNSET, + buyer_id: str | Unset = UNSET, + item_id: int | Unset = UNSET, + offer_status: str | Unset = UNSET, ) -> Response[ConversationPage | ErrorResponse]: """List the seller's conversations @@ -223,7 +263,12 @@ async def asyncio_detailed( the first page to see it. Pass the `nextCursor` of a page as `cursor` with the same filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to a period of the last message: `from` is inclusive, `to` exclusive, and the period is read page by page like the - whole list. Requires `conversations:read`. + whole list. `buyerId`, `itemId` and `offerStatus` combine with the other filters (AND): `buyerId` is + the buyer's identifier on the marketplace (a conversation's `buyerId`); `itemId` keeps the + conversations about the item, through their transactions on the marketplace (a conversation the + marketplace ties to no listing of the item is not found); `offerStatus` keeps those with at least + one offer currently at that status, and with `itemId` that same offer is on the item. An `itemId` + that is not one of the seller's items answers an empty page. Requires `conversations:read`. Args: limit (int | Unset): Default: 50. @@ -232,6 +277,9 @@ async def asyncio_detailed( account_id (UUID | Unset): from_ (datetime.datetime | Unset): to (datetime.datetime | Unset): + buyer_id (str | Unset): + item_id (int | Unset): + offer_status (str | Unset): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -248,6 +296,9 @@ async def asyncio_detailed( account_id=account_id, from_=from_, to=to, + buyer_id=buyer_id, + item_id=item_id, + offer_status=offer_status, ) response = await client.get_async_httpx_client().request(**kwargs) @@ -264,6 +315,9 @@ async def asyncio( account_id: UUID | Unset = UNSET, from_: datetime.datetime | Unset = UNSET, to: datetime.datetime | Unset = UNSET, + buyer_id: str | Unset = UNSET, + item_id: int | Unset = UNSET, + offer_status: str | Unset = UNSET, ) -> ConversationPage | ErrorResponse | None: """List the seller's conversations @@ -272,7 +326,12 @@ async def asyncio( the first page to see it. Pass the `nextCursor` of a page as `cursor` with the same filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to a period of the last message: `from` is inclusive, `to` exclusive, and the period is read page by page like the - whole list. Requires `conversations:read`. + whole list. `buyerId`, `itemId` and `offerStatus` combine with the other filters (AND): `buyerId` is + the buyer's identifier on the marketplace (a conversation's `buyerId`); `itemId` keeps the + conversations about the item, through their transactions on the marketplace (a conversation the + marketplace ties to no listing of the item is not found); `offerStatus` keeps those with at least + one offer currently at that status, and with `itemId` that same offer is on the item. An `itemId` + that is not one of the seller's items answers an empty page. Requires `conversations:read`. Args: limit (int | Unset): Default: 50. @@ -281,6 +340,9 @@ async def asyncio( account_id (UUID | Unset): from_ (datetime.datetime | Unset): to (datetime.datetime | Unset): + buyer_id (str | Unset): + item_id (int | Unset): + offer_status (str | Unset): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -299,5 +361,8 @@ async def asyncio( account_id=account_id, from_=from_, to=to, + buyer_id=buyer_id, + item_id=item_id, + offer_status=offer_status, ) ).parsed diff --git a/src/controlresell/generated/api/favorites/__init__.py b/src/controlresell/generated/api/favorites/__init__.py new file mode 100644 index 0000000..2d7c0b2 --- /dev/null +++ b/src/controlresell/generated/api/favorites/__init__.py @@ -0,0 +1 @@ +"""Contains endpoint functions for accessing the API""" diff --git a/src/controlresell/generated/api/favorites/list_favorites.py b/src/controlresell/generated/api/favorites/list_favorites.py new file mode 100644 index 0000000..90c3390 --- /dev/null +++ b/src/controlresell/generated/api/favorites/list_favorites.py @@ -0,0 +1,311 @@ +import datetime +from http import HTTPStatus +from typing import Any +from uuid import UUID + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.favorite_page import FavoritePage +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, + account_id: UUID | Unset = UNSET, + item_id: int | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + json_from_: str | Unset = UNSET + if not isinstance(from_, Unset): + json_from_ = from_.isoformat() + params["from"] = json_from_ + + json_to: str | Unset = UNSET + if not isinstance(to, Unset): + json_to = to.isoformat() + params["to"] = json_to + + json_account_id: str | Unset = UNSET + if not isinstance(account_id, Unset): + json_account_id = str(account_id) + params["accountId"] = json_account_id + + params["itemId"] = item_id + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/favorites", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | FavoritePage: + if response.status_code == 200: + response_200 = FavoritePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | FavoritePage]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, + account_id: UUID | Unset = UNSET, + item_id: int | Unset = UNSET, +) -> Response[ErrorResponse | FavoritePage]: + """List the favorites of the seller's listings + + The favorites of the listings of every marketplace account of the seller. A favorite is a buyer of + the marketplace who put one of the seller's listings in their favorites, named by their identifier + on the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. An `accountId` or an `itemId` + that is not the seller's answers an empty page. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + account_id (UUID | Unset): + item_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | FavoritePage] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + from_=from_, + to=to, + account_id=account_id, + item_id=item_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, + account_id: UUID | Unset = UNSET, + item_id: int | Unset = UNSET, +) -> ErrorResponse | FavoritePage | None: + """List the favorites of the seller's listings + + The favorites of the listings of every marketplace account of the seller. A favorite is a buyer of + the marketplace who put one of the seller's listings in their favorites, named by their identifier + on the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. An `accountId` or an `itemId` + that is not the seller's answers an empty page. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + account_id (UUID | Unset): + item_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | FavoritePage + """ + + return sync_detailed( + client=client, + limit=limit, + cursor=cursor, + from_=from_, + to=to, + account_id=account_id, + item_id=item_id, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, + account_id: UUID | Unset = UNSET, + item_id: int | Unset = UNSET, +) -> Response[ErrorResponse | FavoritePage]: + """List the favorites of the seller's listings + + The favorites of the listings of every marketplace account of the seller. A favorite is a buyer of + the marketplace who put one of the seller's listings in their favorites, named by their identifier + on the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. An `accountId` or an `itemId` + that is not the seller's answers an empty page. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + account_id (UUID | Unset): + item_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | FavoritePage] + """ + + kwargs = _get_kwargs( + limit=limit, + cursor=cursor, + from_=from_, + to=to, + account_id=account_id, + item_id=item_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, + account_id: UUID | Unset = UNSET, + item_id: int | Unset = UNSET, +) -> ErrorResponse | FavoritePage | None: + """List the favorites of the seller's listings + + The favorites of the listings of every marketplace account of the seller. A favorite is a buyer of + the marketplace who put one of the seller's listings in their favorites, named by their identifier + on the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. An `accountId` or an `itemId` + that is not the seller's answers an empty page. Requires `items:read`. + + Args: + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + account_id (UUID | Unset): + item_id (int | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | FavoritePage + """ + + return ( + await asyncio_detailed( + client=client, + limit=limit, + cursor=cursor, + from_=from_, + to=to, + account_id=account_id, + item_id=item_id, + ) + ).parsed diff --git a/src/controlresell/generated/api/favorites/list_item_favorites.py b/src/controlresell/generated/api/favorites/list_item_favorites.py new file mode 100644 index 0000000..82d8032 --- /dev/null +++ b/src/controlresell/generated/api/favorites/list_item_favorites.py @@ -0,0 +1,294 @@ +import datetime +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.favorite_page import FavoritePage +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + id: int, + *, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, +) -> dict[str, Any]: + + params: dict[str, Any] = {} + + params["limit"] = limit + + params["cursor"] = cursor + + json_from_: str | Unset = UNSET + if not isinstance(from_, Unset): + json_from_ = from_.isoformat() + params["from"] = json_from_ + + json_to: str | Unset = UNSET + if not isinstance(to, Unset): + json_to = to.isoformat() + params["to"] = json_to + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/api/public/v1/items/{id}/favorites".format( + id=quote(str(id), safe=""), + ), + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | FavoritePage: + if response.status_code == 200: + response_200 = FavoritePage.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 402: + response_402 = ErrorResponse.from_dict(response.json()) + + return response_402 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + response_default = ErrorResponse.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | FavoritePage]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + id: int, + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, +) -> Response[ErrorResponse | FavoritePage]: + """List the favorites of an item + + The favorites of the item's listings, on every account it is listed on. A favorite is a buyer of the + marketplace who put one of the seller's listings in their favorites, named by their identifier on + the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. Requires `items:read`. + + Args: + id (int): + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | FavoritePage] + """ + + kwargs = _get_kwargs( + id=id, + limit=limit, + cursor=cursor, + from_=from_, + to=to, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + id: int, + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, +) -> ErrorResponse | FavoritePage | None: + """List the favorites of an item + + The favorites of the item's listings, on every account it is listed on. A favorite is a buyer of the + marketplace who put one of the seller's listings in their favorites, named by their identifier on + the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. Requires `items:read`. + + Args: + id (int): + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | FavoritePage + """ + + return sync_detailed( + id=id, + client=client, + limit=limit, + cursor=cursor, + from_=from_, + to=to, + ).parsed + + +async def asyncio_detailed( + id: int, + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, +) -> Response[ErrorResponse | FavoritePage]: + """List the favorites of an item + + The favorites of the item's listings, on every account it is listed on. A favorite is a buyer of the + marketplace who put one of the seller's listings in their favorites, named by their identifier on + the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. Requires `items:read`. + + Args: + id (int): + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | FavoritePage] + """ + + kwargs = _get_kwargs( + id=id, + limit=limit, + cursor=cursor, + from_=from_, + to=to, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + id: int, + *, + client: AuthenticatedClient | Client, + limit: int | Unset = 50, + cursor: str | Unset = UNSET, + from_: datetime.datetime | Unset = UNSET, + to: datetime.datetime | Unset = UNSET, +) -> ErrorResponse | FavoritePage | None: + """List the favorites of an item + + The favorites of the item's listings, on every account it is listed on. A favorite is a buyer of the + marketplace who put one of the seller's listings in their favorites, named by their identifier on + the marketplace (`buyerId`). Its `item` is a summary of the item of the listing, `null` when + ControlResell does not follow the listing. The most recent first (by `createdAt`, then `id`), one + page at a time: pass the `nextCursor` of a page as `cursor` to read the next one, with the same + filters (a cursor reused with other filters is an `invalid_cursor`). `from` and `to` go straight to + a period of the favorite's date: `from` is inclusive, `to` exclusive. Requires `items:read`. + + Args: + id (int): + limit (int | Unset): Default: 50. + cursor (str | Unset): + from_ (datetime.datetime | Unset): + to (datetime.datetime | Unset): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | FavoritePage + """ + + return ( + await asyncio_detailed( + id=id, + client=client, + limit=limit, + cursor=cursor, + from_=from_, + to=to, + ) + ).parsed diff --git a/src/controlresell/generated/models/__init__.py b/src/controlresell/generated/models/__init__.py index 8abda0a..609876e 100644 --- a/src/controlresell/generated/models/__init__.py +++ b/src/controlresell/generated/models/__init__.py @@ -23,6 +23,9 @@ from .customer_address import CustomerAddress from .customer_page import CustomerPage from .error_response import ErrorResponse +from .favorite import Favorite +from .favorite_item import FavoriteItem +from .favorite_page import FavoritePage from .item import Item from .item_attribute import ItemAttribute from .item_create_request import ItemCreateRequest @@ -90,6 +93,9 @@ "CustomerAddress", "CustomerPage", "ErrorResponse", + "Favorite", + "FavoriteItem", + "FavoritePage", "Item", "ItemAttribute", "ItemCreateRequest", diff --git a/src/controlresell/generated/models/conversation.py b/src/controlresell/generated/models/conversation.py index 267cb03..10fb8ae 100644 --- a/src/controlresell/generated/models/conversation.py +++ b/src/controlresell/generated/models/conversation.py @@ -28,6 +28,7 @@ class Conversation: updated_at (datetime.datetime): platform (None | str | Unset): buyer_login (None | str | Unset): + buyer_id (None | str | Unset): last_message (Message | None | Unset): last_message_at (datetime.datetime | None | Unset): """ @@ -39,6 +40,7 @@ class Conversation: updated_at: datetime.datetime platform: None | str | Unset = UNSET buyer_login: None | str | Unset = UNSET + buyer_id: None | str | Unset = UNSET last_message: Message | None | Unset = UNSET last_message_at: datetime.datetime | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -68,6 +70,12 @@ def to_dict(self) -> dict[str, Any]: else: buyer_login = self.buyer_login + buyer_id: None | str | Unset + if isinstance(self.buyer_id, Unset): + buyer_id = UNSET + else: + buyer_id = self.buyer_id + last_message: dict[str, Any] | None | Unset if isinstance(self.last_message, Unset): last_message = UNSET @@ -99,6 +107,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["platform"] = platform if buyer_login is not UNSET: field_dict["buyerLogin"] = buyer_login + if buyer_id is not UNSET: + field_dict["buyerId"] = buyer_id if last_message is not UNSET: field_dict["lastMessage"] = last_message if last_message_at is not UNSET: @@ -139,6 +149,15 @@ def _parse_buyer_login(data: object) -> None | str | Unset: buyer_login = _parse_buyer_login(d.pop("buyerLogin", UNSET)) + def _parse_buyer_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + buyer_id = _parse_buyer_id(d.pop("buyerId", UNSET)) + def _parse_last_message(data: object) -> Message | None | Unset: if data is None: return data @@ -181,6 +200,7 @@ def _parse_last_message_at(data: object) -> datetime.datetime | None | Unset: updated_at=updated_at, platform=platform, buyer_login=buyer_login, + buyer_id=buyer_id, last_message=last_message, last_message_at=last_message_at, ) diff --git a/src/controlresell/generated/models/favorite.py b/src/controlresell/generated/models/favorite.py new file mode 100644 index 0000000..8c95373 --- /dev/null +++ b/src/controlresell/generated/models/favorite.py @@ -0,0 +1,207 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast +from uuid import UUID + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.favorite_item import FavoriteItem + + +T = TypeVar("T", bound="Favorite") + + +@_attrs_define +class Favorite: + """ + Attributes: + id (UUID): + account_id (UUID): + buyer_id (str): + created_at (datetime.datetime): + platform (None | str | Unset): + message_sent_at (datetime.datetime | None | Unset): + listing_id (None | Unset | UUID): + item (FavoriteItem | None | Unset): + """ + + id: UUID + account_id: UUID + buyer_id: str + created_at: datetime.datetime + platform: None | str | Unset = UNSET + message_sent_at: datetime.datetime | None | Unset = UNSET + listing_id: None | Unset | UUID = UNSET + item: FavoriteItem | None | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.favorite_item import FavoriteItem + + id = str(self.id) + + account_id = str(self.account_id) + + buyer_id = self.buyer_id + + created_at = self.created_at.isoformat() + + platform: None | str | Unset + if isinstance(self.platform, Unset): + platform = UNSET + else: + platform = self.platform + + message_sent_at: None | str | Unset + if isinstance(self.message_sent_at, Unset): + message_sent_at = UNSET + elif isinstance(self.message_sent_at, datetime.datetime): + message_sent_at = self.message_sent_at.isoformat() + else: + message_sent_at = self.message_sent_at + + listing_id: None | str | Unset + if isinstance(self.listing_id, Unset): + listing_id = UNSET + elif isinstance(self.listing_id, UUID): + listing_id = str(self.listing_id) + else: + listing_id = self.listing_id + + item: dict[str, Any] | None | Unset + if isinstance(self.item, Unset): + item = UNSET + elif isinstance(self.item, FavoriteItem): + item = self.item.to_dict() + else: + item = self.item + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "accountId": account_id, + "buyerId": buyer_id, + "createdAt": created_at, + } + ) + if platform is not UNSET: + field_dict["platform"] = platform + if message_sent_at is not UNSET: + field_dict["messageSentAt"] = message_sent_at + if listing_id is not UNSET: + field_dict["listingId"] = listing_id + if item is not UNSET: + field_dict["item"] = item + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.favorite_item import FavoriteItem + + d = dict(src_dict) + id = UUID(d.pop("id")) + + account_id = UUID(d.pop("accountId")) + + buyer_id = d.pop("buyerId") + + created_at = datetime.datetime.fromisoformat(d.pop("createdAt")) + + def _parse_platform(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + platform = _parse_platform(d.pop("platform", UNSET)) + + def _parse_message_sent_at(data: object) -> datetime.datetime | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + message_sent_at_type_0 = datetime.datetime.fromisoformat(data) + + return message_sent_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None | Unset, data) + + message_sent_at = _parse_message_sent_at(d.pop("messageSentAt", UNSET)) + + def _parse_listing_id(data: object) -> None | Unset | UUID: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + listing_id_type_0 = UUID(data) + + return listing_id_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | UUID, data) + + listing_id = _parse_listing_id(d.pop("listingId", UNSET)) + + def _parse_item(data: object) -> FavoriteItem | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + item_type_0 = FavoriteItem.from_dict(data) + + return item_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(FavoriteItem | None | Unset, data) + + item = _parse_item(d.pop("item", UNSET)) + + favorite = cls( + id=id, + account_id=account_id, + buyer_id=buyer_id, + created_at=created_at, + platform=platform, + message_sent_at=message_sent_at, + listing_id=listing_id, + item=item, + ) + + favorite.additional_properties = d + return favorite + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/favorite_item.py b/src/controlresell/generated/models/favorite_item.py new file mode 100644 index 0000000..2ce6381 --- /dev/null +++ b/src/controlresell/generated/models/favorite_item.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +if TYPE_CHECKING: + from ..models.money import Money + + +T = TypeVar("T", bound="FavoriteItem") + + +@_attrs_define +class FavoriteItem: + """ + Attributes: + id (int): + name (str): + price (Money): + sold (bool): + """ + + id: int + name: str + price: Money + sold: bool + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + id = self.id + + name = self.name + + price = self.price.to_dict() + + sold = self.sold + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "id": id, + "name": name, + "price": price, + "sold": sold, + } + ) + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.money import Money + + d = dict(src_dict) + id = d.pop("id") + + name = d.pop("name") + + price = Money.from_dict(d.pop("price")) + + sold = d.pop("sold") + + favorite_item = cls( + id=id, + name=name, + price=price, + sold=sold, + ) + + favorite_item.additional_properties = d + return favorite_item + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/src/controlresell/generated/models/favorite_page.py b/src/controlresell/generated/models/favorite_page.py new file mode 100644 index 0000000..4471029 --- /dev/null +++ b/src/controlresell/generated/models/favorite_page.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Self, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.favorite import Favorite + + +T = TypeVar("T", bound="FavoritePage") + + +@_attrs_define +class FavoritePage: + """ + Attributes: + data (list[Favorite]): + next_cursor (None | str | Unset): + """ + + data: list[Favorite] + next_cursor: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + data = [] + for data_item_data in self.data: + data_item = data_item_data.to_dict() + data.append(data_item) + + next_cursor: None | str | Unset + if isinstance(self.next_cursor, Unset): + next_cursor = UNSET + else: + next_cursor = self.next_cursor + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "data": data, + } + ) + if next_cursor is not UNSET: + field_dict["nextCursor"] = next_cursor + + return field_dict + + @classmethod + def from_dict(cls, src_dict: Mapping[str, Any]) -> Self: + from ..models.favorite import Favorite + + d = dict(src_dict) + data = [] + _data = d.pop("data") + for data_item_data in _data: + data_item = Favorite.from_dict(data_item_data) + + data.append(data_item) + + def _parse_next_cursor(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + next_cursor = _parse_next_cursor(d.pop("nextCursor", UNSET)) + + favorite_page = cls( + data=data, + next_cursor=next_cursor, + ) + + favorite_page.additional_properties = d + return favorite_page + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/tests/test_client.py b/tests/test_client.py index b677161..4b6d8c1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -368,6 +368,52 @@ def test_customers_get_reads_one_customer(): assert requests[0].url.path == f"/api/public/v1/customers/{ACCOUNT}" +FAVORITE = { + "id": "11111111-1111-1111-1111-111111111111", + "accountId": "11111111-1111-1111-1111-111111111111", + "platform": "VINTED", + "buyerId": "b1", + "createdAt": "2026-10-24T00:00:00Z", + "messageSentAt": None, + "listingId": "L1", + "item": {"id": 42, "name": "Jacket", "price": {"amount": "12.50", "currency": "EUR"}, "sold": False}, +} + + +def test_favorites_iter_follows_the_cursor_with_the_same_filters(): + import datetime + + seen = [] + + def handler(request): + seen.append(request.url) + if request.url.params.get("cursor"): + return reply({"data": [{**FAVORITE, "buyerId": "b2", "item": None}], "nextCursor": None}) + return reply({"data": [FAVORITE], "nextCursor": "c2"}) + + _, sdk = client(handler) + start = datetime.datetime(2026, 10, 1, tzinfo=datetime.timezone.utc) + favorites = list(sdk.favorites.iter(account_id=ACCOUNT, item_id=42, from_=start, limit=1)) + assert [f.buyer_id for f in favorites] == ["b1", "b2"] + assert favorites[0].item.name == "Jacket" and favorites[1].item is None + assert [u.path for u in seen] == ["/api/public/v1/favorites"] * 2 + assert [u.params["itemId"] for u in seen] == ["42", "42"] and [u.params["accountId"] for u in seen] == [ACCOUNT] * 2 + assert seen[0].params["from"] == start.isoformat() and seen[1].params["cursor"] == "c2" + + +def test_favorites_iter_item_reads_the_favorites_of_one_item(): + requests, sdk = client(lambda r: reply({"data": [FAVORITE], "nextCursor": None})) + assert [f.buyer_id for f in sdk.favorites.iter_item(42)] == ["b1"] + assert requests[0].url.path == "/api/public/v1/items/42/favorites" + + +def test_conversations_list_sends_the_buyer_item_and_offer_status_filters(): + requests, sdk = client(lambda r: reply({"data": [], "nextCursor": None})) + sdk.conversations.list(buyer_id="b-1", item_id=42, offer_status="PENDING") + params = requests[0].url.params + assert params["buyerId"] == "b-1" and params["itemId"] == "42" and params["offerStatus"] == "PENDING" + + def test_catalogs_iter_brands_follows_the_cursor_with_the_same_query(): seen = []