From ccd9e84fe8e02f2aa28a2074dc3c5b84e92c0761 Mon Sep 17 00:00:00 2001 From: Ryan Thomson Date: Mon, 17 Aug 2026 09:53:55 -0400 Subject: [PATCH 1/4] Add Ruff and update uv --- pyproject.toml | 16 +++++++++++++--- uv.lock | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 168c1b6..2b98674 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,8 @@ name = "bigc" version = "1.0.0" description = "Unofficial client for the BigCommerce API" -license = { text = "MIT" } +license = "MIT" +license-files = ["LICENSE.txt"] readme = "README.md" requires-python = ">=3.10" authors = [ @@ -15,7 +16,6 @@ keywords = ["bigcommerce", "api", "client"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -34,8 +34,18 @@ repository = "https://github.com/MedShift/bigc.git" [dependency-groups] dev = [ "pytest~=7.1", + "ruff==0.16.3", ] [build-system] -requires = ["uv_build>=0.9.5,<0.10.0"] +requires = ["uv_build>=0.12.5,<0.13.0"] build-backend = "uv_build" + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = [ + "F401", +] + +[tool.ruff.format] +line-ending = "lf" +quote-style = "single" diff --git a/uv.lock b/uv.lock index 5634ea2..5d0b9ec 100644 --- a/uv.lock +++ b/uv.lock @@ -13,13 +13,17 @@ dependencies = [ [package.dev-dependencies] dev = [ { name = "pytest" }, + { name = "ruff" }, ] [package.metadata] requires-dist = [{ name = "requests", specifier = "~=2.32" }] [package.metadata.requires-dev] -dev = [{ name = "pytest", specifier = "~=7.1" }] +dev = [ + { name = "pytest", specifier = "~=7.1" }, + { name = "ruff", specifier = "==0.16.3" }, +] [[package]] name = "certifi" @@ -133,7 +137,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -208,6 +212,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, ] +[[package]] +name = "ruff" +version = "0.16.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/b3/3213589383f8f1b3938781bd1278713f6d18621a14992b3e81fefb8a5ef9/ruff-0.16.3.tar.gz", hash = "sha256:e76d33a347661a84b5be6d043d0347fdc745dfdcf825a8f4fed64b5e26eebdf2", size = 4891904, upload-time = "2026-08-13T15:17:13.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/96/493770daebd68c0a67f1549fdf519f53be51fc435186c0585bcc272fd76c/ruff-0.16.3-py3-none-linux_armv6l.whl", hash = "sha256:0c5710e247a58a4521e66e124ba9a74655b414f61ba3a2e9e3811e11098f48f7", size = 10902799, upload-time = "2026-08-13T15:16:27.382Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/2becf3942fddc29a29b8df47691d456fb1085391a694f74d84513251418c/ruff-0.16.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fe155130631a2471fd2e14a7a664a4dfbd7194b8229c3d7b2a40b21178639081", size = 11135539, upload-time = "2026-08-13T15:16:30.87Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1e/4b8b72f0d006dbf19326aa99f9ca0ee2ff374187c4d301cf529a51aa06fe/ruff-0.16.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e2ed719e14aa64d895c2ee922594a90a43c861a93f0575a95ff8c47cdbd13eb9", size = 10475095, upload-time = "2026-08-13T15:16:33.259Z" }, + { url = "https://files.pythonhosted.org/packages/92/32/2201fa49ba1f6c101ee321e83f051ac7a4b8d07b0ef6b4d3f2772b302275/ruff-0.16.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e0b1da805eb043654645d74d5de1e5ce2edc686e40790d2b86f56d71cc06a84", size = 10668771, upload-time = "2026-08-13T15:16:35.65Z" }, + { url = "https://files.pythonhosted.org/packages/c3/66/4afc5c8363bd04d45effce1b7c8713ca037d7a6740b7451a2403a6e3a972/ruff-0.16.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a37bdea0bbe21780f590bf437d6412c8c4e1b6cd010f91a65c2c40c5e5f5f870", size = 10699568, upload-time = "2026-08-13T15:16:38.195Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/c67d246bf36bf1698551c56de39e95cd07f70e64433e0098e6267d77061b/ruff-0.16.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09571e6d1288ed9be475207a3ac04ada404f1cd898104be0f6ab8d7df438575b", size = 11499365, upload-time = "2026-08-13T15:16:40.623Z" }, + { url = "https://files.pythonhosted.org/packages/67/0b/00ecbceb99a263af7b12f6f05ac3c92bc47b905e91adc3f207a836e3bc01/ruff-0.16.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c18c5a101eb540010638cc1ff3c84944d3adb3df62b8d98ca8f22ba484d3413", size = 12311728, upload-time = "2026-08-13T15:16:43.564Z" }, + { url = "https://files.pythonhosted.org/packages/54/b2/b7b3bb54f4d3f7db504e476ad4ab8de530dceebe2c061384b2757ee419e8/ruff-0.16.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8457c44f15033c85ddbb77b15d451df9e24e4bd03b628396dd3610cedc3b8f82", size = 11699896, upload-time = "2026-08-13T15:16:46.209Z" }, + { url = "https://files.pythonhosted.org/packages/c7/30/4c468429ac195addc5ee1b717b6ab1b66632786737ca3b2ed3443fb0c26a/ruff-0.16.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:294b95c4ae0cda9388525c2047778aa758d6b8d4bb876fd4e9eaa3ebc92343eb", size = 11058736, upload-time = "2026-08-13T15:16:48.823Z" }, + { url = "https://files.pythonhosted.org/packages/43/67/7a113cdaddf24b64d7f75b1242a99d04c82fcef4f6921fdbb832beaffb5f/ruff-0.16.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3d0c7c40c87c2a820509c31ba007968da6e1306468c067b2d82fbfdbcd0e8474", size = 11586911, upload-time = "2026-08-13T15:16:51.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c1/2e66f24c0f3ead25a5e660111778685e505e5da353c82802bf49f0cbe7b9/ruff-0.16.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9f738c0fdfa8eed0b2ce7fb27ee7258208a92a68d7949e62aa15164bc7b389da", size = 10954265, upload-time = "2026-08-13T15:16:54.763Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ba/4cee23bf52cba9a058d3726de623624daf50ef9638868edd86f4126157f6/ruff-0.16.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb785f0be25abe69d320415cd4f833b59e17ba7613d9ba6a958023b6bceb0a50", size = 10709886, upload-time = "2026-08-13T15:16:57.339Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/7da7194fa5d9dc0a285f7e6fa5a4722e7c63faac0b45b614ded9314363a1/ruff-0.16.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c5536e3acfbf9563085aa2be7b13c629c3077e902afc5b941ac44024dbb9f506", size = 11210392, upload-time = "2026-08-13T15:17:00.171Z" }, + { url = "https://files.pythonhosted.org/packages/35/85/7795f6e817af050e7517bf3e7aa9b061cce70ef33d280aad902c956c1ecf/ruff-0.16.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a2d85c02f9b8e165d85e6779184d38c4132de12603dab59c51c28e22584f9e4d", size = 11626910, upload-time = "2026-08-13T15:17:03.299Z" }, + { url = "https://files.pythonhosted.org/packages/78/9b/475b927cf27a5cbbda3c7bafb69ed6ff77e1d7923d5d85f17c2749d7ae32/ruff-0.16.3-py3-none-win32.whl", hash = "sha256:388cdf2166642bd9b13d52b5932d3170f34f8abed7e8d9a855f1d84b83645a0a", size = 10931415, upload-time = "2026-08-13T15:17:05.726Z" }, + { url = "https://files.pythonhosted.org/packages/b2/99/e2a2bfc4fbf0a1e8a916bc9ebe6fe6c58cc34c28e0ffc6ce281d572d1c2e/ruff-0.16.3-py3-none-win_amd64.whl", hash = "sha256:e80a7d69ca2a6d1c4d352ec91458cdca6e56c83cdbcabd93e4abe1e53591d948", size = 11445993, upload-time = "2026-08-13T15:17:08.353Z" }, + { url = "https://files.pythonhosted.org/packages/69/3e/4132e539aed78c148854d4997a2685b0ed4dc4e87110b59ce528564e184e/ruff-0.16.3-py3-none-win_arm64.whl", hash = "sha256:b8ca152da82c1acc1fa8d5874b15951935f0eef46f10e6954c83859011b6178a", size = 11399302, upload-time = "2026-08-13T15:17:10.908Z" }, +] + [[package]] name = "tomli" version = "2.3.0" From 945e183c36d109e10d9699bcc40af6a431a0a7ec Mon Sep 17 00:00:00 2001 From: Ryan Thomson Date: Mon, 17 Aug 2026 09:54:10 -0400 Subject: [PATCH 2/4] Format with Ruff --- src/bigc/api.py | 40 +++- src/bigc/api_client.py | 162 +++++++------ src/bigc/data/order_status.py | 1 + src/bigc/exceptions.py | 45 ++-- src/bigc/resources/carts_v3.py | 131 +++++++---- src/bigc/resources/categories_v3.py | 64 +++-- src/bigc/resources/checkouts_v3.py | 218 +++++++++++------- src/bigc/resources/currencies_v2.py | 36 +-- src/bigc/resources/customer_groups_v2.py | 73 +++--- src/bigc/resources/customers_v3.py | 211 +++++++++-------- src/bigc/resources/orders_v2.py | 269 +++++++++++++--------- src/bigc/resources/orders_v3.py | 76 +++--- src/bigc/resources/pricing_v3.py | 17 +- src/bigc/resources/product_variants_v3.py | 96 +++++--- src/bigc/resources/products_v3.py | 84 ++++--- src/bigc/resources/webhooks_v3.py | 69 ++++-- tests/test_api.py | 5 +- tests/test_api_client.py | 23 +- tests/test_exceptions.py | 121 ++++++---- tests/test_utils.py | 42 +++- 20 files changed, 1089 insertions(+), 694 deletions(-) diff --git a/src/bigc/api.py b/src/bigc/api.py index b89b61d..39bffa3 100644 --- a/src/bigc/api.py +++ b/src/bigc/api.py @@ -6,35 +6,51 @@ class BigCommerceAPI: def __init__( - self, - store_hash: str, - access_token: str, - *, - timeout: float | None = None, - get_retries: int | None = None + self, + store_hash: str, + access_token: str, + *, + timeout: float | None = None, + get_retries: int | None = None, ): # Shared so that both API versions use the same pool within a thread thread_local = threading.local() api_v2 = BigCommerceV2APIClient( - store_hash, access_token, timeout=timeout, get_retries=get_retries, _thread_local=thread_local, + store_hash, + access_token, + timeout=timeout, + get_retries=get_retries, + _thread_local=thread_local, ) api_v3 = BigCommerceV3APIClient( - store_hash, access_token, timeout=timeout, get_retries=get_retries, _thread_local=thread_local, + store_hash, + access_token, + timeout=timeout, + get_retries=get_retries, + _thread_local=thread_local, ) self.api_v2 = api_v2 self.api_v3 = api_v3 self.carts_v3: BigCommerceCartsV3API = BigCommerceCartsV3API(api_v3) - self.categories_v3: BigCommerceCategoriesV3API = BigCommerceCategoriesV3API(api_v3) + self.categories_v3: BigCommerceCategoriesV3API = BigCommerceCategoriesV3API( + api_v3 + ) self.checkouts_v3: BigCommerceCheckoutsV3API = BigCommerceCheckoutsV3API(api_v3) - self.currencies_v2: BigCommerceCurrenciesV2API = BigCommerceCurrenciesV2API(api_v2) - self.customer_groups_v2: BigCommerceCustomerGroupsV2API = BigCommerceCustomerGroupsV2API(api_v2) + self.currencies_v2: BigCommerceCurrenciesV2API = BigCommerceCurrenciesV2API( + api_v2 + ) + self.customer_groups_v2: BigCommerceCustomerGroupsV2API = ( + BigCommerceCustomerGroupsV2API(api_v2) + ) self.customers_v3: BigCommerceCustomersV3API = BigCommerceCustomersV3API(api_v3) self.orders_v2: BigCommerceOrdersV2API = BigCommerceOrdersV2API(api_v2) self.orders_v3: BigCommerceOrdersV3API = BigCommerceOrdersV3API(api_v3) self.pricing_v3: BigCommercePricingV3API = BigCommercePricingV3API(api_v3) - self.product_variants_v3: BigCommerceProductVariantsV3API = BigCommerceProductVariantsV3API(api_v3) + self.product_variants_v3: BigCommerceProductVariantsV3API = ( + BigCommerceProductVariantsV3API(api_v3) + ) self.products_v3: BigCommerceProductsV3API = BigCommerceProductsV3API(api_v3) self.webhooks_v3: BigCommerceWebhooksV3API = BigCommerceWebhooksV3API(api_v3) diff --git a/src/bigc/api_client.py b/src/bigc/api_client.py index 4a4e4b4..b8d638c 100644 --- a/src/bigc/api_client.py +++ b/src/bigc/api_client.py @@ -1,7 +1,8 @@ import itertools import threading from abc import ABC, abstractmethod -from typing import Any, Iterator, NoReturn +from collections.abc import Iterator +from typing import Any, NoReturn import requests @@ -20,13 +21,13 @@ class BigCommerceRequestClient(ABC): def __init__( - self, - store_hash: str, - access_token: str, - *, - timeout: float | None = None, - get_retries: int | None = None, - _thread_local: threading.local | None = None, + self, + store_hash: str, + access_token: str, + *, + timeout: float | None = None, + get_retries: int | None = None, + _thread_local: threading.local | None = None, ): self.store_hash = store_hash self.access_token = access_token @@ -48,15 +49,15 @@ def _session(self) -> requests.Session: return self._thread_local.session def request( - self, - method: str, - path: str, - *, - data: Any = None, - params: dict[str, Any] | None = None, - headers: dict[str, str] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + method: str, + path: str, + *, + data: Any = None, + params: dict[str, Any] | None = None, + headers: dict[str, str] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Any: method = method.upper() @@ -103,11 +104,11 @@ def perform_request() -> Any: try: return perform_request() except ( - InternalServerError, - BadGatewayError, - ServiceUnavailableError, - GatewayTimeoutError, - BigCommerceNetworkError, + InternalServerError, + BadGatewayError, + ServiceUnavailableError, + GatewayTimeoutError, + BigCommerceNetworkError, ) as exc: last_exc = exc @@ -131,16 +132,15 @@ def delete(self, *args, **kwargs): @abstractmethod def get_many( - self, - path: str, - *, - page_size: int | None = None, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + path: str, + *, + page_size: int | None = None, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[Any]: """Make a request to a paginated BigCommerce API endpoint""" - pass @abstractmethod def _prepare_url(self, path: str) -> str: @@ -185,11 +185,15 @@ def _process_param(value: Any) -> str: @staticmethod def _handle_error_response(response: requests.Response) -> NoReturn: try: - message, errors = BigCommerceException.extract_error_message(response.json()) + message, errors = BigCommerceException.extract_error_message( + response.json() + ) except requests.JSONDecodeError: message, errors = None, None - exc_class = BigCommerceException.get_exc_class_for_status_code(response.status_code) + exc_class = BigCommerceException.get_exc_class_for_status_code( + response.status_code + ) raise exc_class( message=message, status_code=response.status_code, @@ -202,30 +206,34 @@ class BigCommerceV2APIClient(BigCommerceRequestClient): """A client for directly calling BigCommerce v2 API endpoints""" def _prepare_url(self, path: str) -> str: - return f"https://api.bigcommerce.com/stores/{self.store_hash}/v2/{path.lstrip('/')}" + return f'https://api.bigcommerce.com/stores/{self.store_hash}/v2/{path.lstrip("/")}' def get_many( - self, - path: str, - *, - page_size: int | None = None, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + path: str, + *, + page_size: int | None = None, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[Any]: page_size = MAX_V2_PAGE_SIZE if page_size is None else int(page_size) params = {**params} if params else {} if params.keys() & {'limit', 'offset'}: - raise ValueError('params already has pagination values (limit and/or offset)') + raise ValueError( + 'params already has pagination values (limit and/or offset)' + ) params['limit'] = page_size for cur_page in itertools.count(1): params['page'] = cur_page - res_data = super().get(path, params=params, timeout=timeout, retries=retries) + res_data = super().get( + path, params=params, timeout=timeout, retries=retries + ) # The API returns HTTP 204 (empty) past the last page if res_data is None: @@ -245,7 +253,7 @@ class BigCommerceV3APIClient(BigCommerceRequestClient): """A client for directly calling BigCommerce v3 API endpoints""" def _prepare_url(self, path: str) -> str: - return f"https://api.bigcommerce.com/stores/{self.store_hash}/v3/{path.lstrip('/')}" + return f'https://api.bigcommerce.com/stores/{self.store_hash}/v3/{path.lstrip("/")}' def request(self, *args, **kwargs): # v3 response bodies are boxed in the 'data' key @@ -253,16 +261,18 @@ def request(self, *args, **kwargs): return None if response is None else response['data'] def _get_many_using_limit_offset( - self, - path: str, - *, - page_size: int, - params: dict[str, Any], - timeout: float | None, - retries: int | None = None, + self, + path: str, + *, + page_size: int, + params: dict[str, Any], + timeout: float | None, + retries: int | None = None, ) -> Iterator[Any]: if params.keys() & {'limit', 'offset'}: - raise ValueError('params already has pagination values (limit and/or offset)') + raise ValueError( + 'params already has pagination values (limit and/or offset)' + ) params['limit'] = page_size @@ -271,53 +281,59 @@ def _get_many_using_limit_offset( while cur_page <= num_pages: params['page'] = cur_page - res_data = super().request('GET', path, params=params, timeout=timeout, retries=retries) + res_data = super().request( + 'GET', path, params=params, timeout=timeout, retries=retries + ) cur_page += 1 num_pages = int(res_data['meta']['pagination']['total_pages']) if not isinstance(res_data['data'], list): - raise TypeError(f"expected list, got {type(res_data['data']).__name__}") + raise TypeError(f'expected list, got {type(res_data["data"]).__name__}') yield from res_data['data'] def _get_many_using_cursor( - self, - path: str, - *, - page_size: int, - params: dict[str, Any], - timeout: float | None, - retries: int | None = None, + self, + path: str, + *, + page_size: int, + params: dict[str, Any], + timeout: float | None, + retries: int | None = None, ) -> Iterator[Any]: if params.keys() & {'limit', 'before', 'after'}: - raise ValueError('params already has pagination values (limit, before, and/or after)') + raise ValueError( + 'params already has pagination values (limit, before, and/or after)' + ) params['limit'] = page_size while True: - response = super().request('GET', path, params=params, timeout=timeout, retries=retries) + response = super().request( + 'GET', path, params=params, timeout=timeout, retries=retries + ) yield from response['data'] if not ( - # end_cursor will still be provided if the next page is empty - response['meta']['cursor_pagination']['links'].get('next') - and response['data'] + # end_cursor will still be provided if the next page is empty + response['meta']['cursor_pagination']['links'].get('next') + and response['data'] ): break params['after'] = response['meta']['cursor_pagination']['end_cursor'] def get_many( - self, - path: str, - *, - page_size: int | None = None, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, - cursor: bool = False, + self, + path: str, + *, + page_size: int | None = None, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, + cursor: bool = False, ) -> Iterator[Any]: page_size = MAX_V3_PAGE_SIZE if page_size is None else int(page_size) params = {**params} if params else {} diff --git a/src/bigc/data/order_status.py b/src/bigc/data/order_status.py index 10b3221..dc97d78 100644 --- a/src/bigc/data/order_status.py +++ b/src/bigc/data/order_status.py @@ -4,6 +4,7 @@ @unique class BigCommerceOrderStatus(IntEnum): """Enum mapping BigCommerce order statuses to their IDs""" + INCOMPLETE = 0 PENDING = 1 SHIPPED = 2 diff --git a/src/bigc/exceptions.py b/src/bigc/exceptions.py index 1592d99..d7950be 100644 --- a/src/bigc/exceptions.py +++ b/src/bigc/exceptions.py @@ -12,11 +12,13 @@ class BigCommerceException(Exception): DEFAULT_MESSAGE: ClassVar[str] = 'Request to BigCommerce failed.' STATUS_CODE: ClassVar[int | None] = None - def __init__(self, - message: str | None = None, - status_code: int | None = None, - response: Any = None, - errors: dict[str, str] | None = None): + def __init__( + self, + message: str | None = None, + status_code: int | None = None, + response: Any = None, + errors: dict[str, str] | None = None, + ): """ :param message: A short description of the error's cause. :param status_code: The HTTP status code of the API response. @@ -39,9 +41,8 @@ def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) # Only include subclasses defined in this file - if inspect.getmodule(cls).__name__ == __name__: - if cls.STATUS_CODE is not None: - _status_code_exc_class_map[cls.STATUS_CODE] = cls + if inspect.getmodule(cls).__name__ == __name__ and cls.STATUS_CODE is not None: + _status_code_exc_class_map[cls.STATUS_CODE] = cls @staticmethod def get_exc_class_for_status_code(status_code: int) -> type[BigCommerceException]: @@ -55,7 +56,9 @@ def get_exc_class_for_status_code(status_code: int) -> type[BigCommerceException return BigCommerceException @staticmethod - def extract_error_message(response_data: object) -> tuple[str | None, dict[str, str] | None]: + def extract_error_message( + response_data: object, + ) -> tuple[str | None, dict[str, str] | None]: message: str | None = None errors: dict[str, str] | None = None @@ -154,22 +157,22 @@ class BigCommerceNetworkError(BigCommerceException): __all__ = ( - 'BigCommerceException', - 'BigCommerceClientError', + 'BadGatewayError', 'BadRequestError', - 'UnauthorizedError', - 'ForbiddenError', - 'DoesNotExistError', + 'BigCommerceClientError', + 'BigCommerceException', + 'BigCommerceNetworkError', + 'BigCommerceServerError', 'ConflictError', + 'DoesNotExistError', 'EntityTooLargeError', + 'ForbiddenError', + 'GatewayTimeoutError', + 'InsufficientStorageError', + 'InternalServerError', 'InvalidDataError', 'LockedError', - 'TooManyRequestsError', - 'BigCommerceServerError', - 'InternalServerError', - 'BadGatewayError', 'ServiceUnavailableError', - 'GatewayTimeoutError', - 'InsufficientStorageError', - 'BigCommerceNetworkError', + 'TooManyRequestsError', + 'UnauthorizedError', ) diff --git a/src/bigc/resources/carts_v3.py b/src/bigc/resources/carts_v3.py index 479805b..68cb95e 100644 --- a/src/bigc/resources/carts_v3.py +++ b/src/bigc/resources/carts_v3.py @@ -11,84 +11,113 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def get( - self, - cart_id: UUIDLike, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + cart_id: UUIDLike, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific cart by its ID""" - return self._api.get(f'/carts/{cart_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/carts/{cart_id}', params=params, timeout=timeout, retries=retries + ) def create( - self, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create a new cart""" return self._api.post('/carts', data=data, params=params, timeout=timeout) def update( - self, - cart_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + cart_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific cart by its ID""" - return self._api.put(f'/carts/{cart_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/carts/{cart_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) - def delete(self, cart_id: UUIDLike, *, timeout: float | None = None, retries: int | None = None) -> None: + def delete( + self, + cart_id: UUIDLike, + *, + timeout: float | None = None, + retries: int | None = None, + ) -> None: """Delete a specific cart by its ID""" self._api.delete(f'/carts/{cart_id}', timeout=timeout, retries=retries) def add_line_items( - self, - cart_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + cart_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Add line items to a cart""" - return self._api.post(f'/carts/{cart_id}/items', data=data, params=params, timeout=timeout) + return self._api.post( + f'/carts/{cart_id}/items', data=data, params=params, timeout=timeout + ) def update_line_item( - self, - cart_id: UUIDLike, - item_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + cart_id: UUIDLike, + item_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a single line item in a cart""" - return self._api.put(f'/carts/{cart_id}/items/{item_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/carts/{cart_id}/items/{item_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) def delete_line_item( - self, - cart_id: UUIDLike, - item_id: UUIDLike, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + cart_id: UUIDLike, + item_id: UUIDLike, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Remove a line item from a cart""" - return self._api.delete(f'/carts/{cart_id}/items/{item_id}', params=params, timeout=timeout, retries=retries) + return self._api.delete( + f'/carts/{cart_id}/items/{item_id}', + params=params, + timeout=timeout, + retries=retries, + ) def create_redirect_url( - self, - cart_id: UUIDLike, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + cart_id: UUIDLike, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create a redirect URL for a cart""" - return self._api.post(f'/carts/{cart_id}/redirect_urls', params=params, timeout=timeout) + return self._api.post( + f'/carts/{cart_id}/redirect_urls', params=params, timeout=timeout + ) diff --git a/src/bigc/resources/categories_v3.py b/src/bigc/resources/categories_v3.py index 645ca73..fd3bf90 100644 --- a/src/bigc/resources/categories_v3.py +++ b/src/bigc/resources/categories_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient @@ -8,34 +9,59 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all categories""" - return self._api.get_many('/catalog/categories', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/catalog/categories', params=params, timeout=timeout, retries=retries + ) - def get(self, category_id: int, *, timeout: float | None = None, retries: int | None = None) -> dict[str, Any]: + def get( + self, + category_id: int, + *, + timeout: float | None = None, + retries: int | None = None, + ) -> dict[str, Any]: """Get a specific category by its ID""" - return self._api.get(f'/catalog/categories/{category_id}', timeout=timeout, retries=retries) + return self._api.get( + f'/catalog/categories/{category_id}', timeout=timeout, retries=retries + ) - def create(self, data: dict[str, Any], *, timeout: float | None = None) -> dict[str, Any]: + def create( + self, data: dict[str, Any], *, timeout: float | None = None + ) -> dict[str, Any]: """Create a category""" return self._api.post('/catalog/categories', data=data, timeout=timeout) def update( - self, - category_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + category_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific category by its ID""" - return self._api.put(f'/catalog/categories/{category_id}', data=data, timeout=timeout, retries=retries) + return self._api.put( + f'/catalog/categories/{category_id}', + data=data, + timeout=timeout, + retries=retries, + ) - def delete(self, category_id: int, *, timeout: float | None = None, retries: int | None = None) -> dict[str, Any]: + def delete( + self, + category_id: int, + *, + timeout: float | None = None, + retries: int | None = None, + ) -> dict[str, Any]: """Delete a specific category by its ID""" - return self._api.delete(f'/catalog/categories/{category_id}', timeout=timeout, retries=retries) + return self._api.delete( + f'/catalog/categories/{category_id}', timeout=timeout, retries=retries + ) diff --git a/src/bigc/resources/checkouts_v3.py b/src/bigc/resources/checkouts_v3.py index a20cba2..4587530 100644 --- a/src/bigc/resources/checkouts_v3.py +++ b/src/bigc/resources/checkouts_v3.py @@ -11,128 +11,180 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def get( - self, - checkout_id: UUIDLike, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + checkout_id: UUIDLike, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific checkout by its ID""" - return self._api.get(f'/checkouts/{checkout_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/checkouts/{checkout_id}', params=params, timeout=timeout, retries=retries + ) def update( - self, - checkout_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + checkout_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Change customer message pertaining to an existing Checkout""" - return self._api.put(f'/checkouts/{checkout_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/checkouts/{checkout_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) def add_billing_address( - self, - checkout_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + checkout_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Add a billing address to an existing checkout""" - return self._api.post(f'/checkouts/{checkout_id}/billing-address', data=data, params=params, timeout=timeout) + return self._api.post( + f'/checkouts/{checkout_id}/billing-address', + data=data, + params=params, + timeout=timeout, + ) def update_billing_address( - self, - checkout_id: UUIDLike, - address_id: str, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + checkout_id: UUIDLike, + address_id: str, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update an existing billing address on a checkout""" - return self._api.put(f'/checkouts/{checkout_id}/billing-address/{address_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/checkouts/{checkout_id}/billing-address/{address_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) def add_consignments( - self, - checkout_id: UUIDLike, - data: list[dict[str, Any]], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + checkout_id: UUIDLike, + data: list[dict[str, Any]], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Add a new consignment to a checkout""" - return self._api.post(f'/checkouts/{checkout_id}/consignments', data=data, params=params, timeout=timeout) + return self._api.post( + f'/checkouts/{checkout_id}/consignments', + data=data, + params=params, + timeout=timeout, + ) def update_consignment( - self, - checkout_id: UUIDLike, - consignment_id: str, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + checkout_id: UUIDLike, + consignment_id: str, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update an existing consignment's selected shipping option""" - return self._api.put(f'/checkouts/{checkout_id}/consignments/{consignment_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/checkouts/{checkout_id}/consignments/{consignment_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) def delete_consignment( - self, - checkout_id: UUIDLike, - consignment_id: str, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + checkout_id: UUIDLike, + consignment_id: str, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Remove an existing consignment from a checkout""" - return self._api.delete(f'/checkouts/{checkout_id}/consignments/{consignment_id}', params=params, timeout=timeout, retries=retries) + return self._api.delete( + f'/checkouts/{checkout_id}/consignments/{consignment_id}', + params=params, + timeout=timeout, + retries=retries, + ) def add_coupon( - self, - checkout_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + checkout_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Add a coupon code to a checkout""" - return self._api.post(f'/checkouts/{checkout_id}/coupons', data=data, params=params, timeout=timeout) + return self._api.post( + f'/checkouts/{checkout_id}/coupons', + data=data, + params=params, + timeout=timeout, + ) def delete_coupon( - self, - checkout_id: UUIDLike, - coupon_code: str, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + checkout_id: UUIDLike, + coupon_code: str, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Delete a coupon code from a checkout""" - return self._api.delete(f'/checkouts/{checkout_id}/coupons/{coupon_code}', params=params, timeout=timeout, retries=retries) + return self._api.delete( + f'/checkouts/{checkout_id}/coupons/{coupon_code}', + params=params, + timeout=timeout, + retries=retries, + ) def add_discounts( - self, - checkout_id: UUIDLike, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + checkout_id: UUIDLike, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Add discounts to an existing checkout""" - return self._api.post(f'/checkouts/{checkout_id}/discounts', data=data, params=params, timeout=timeout) + return self._api.post( + f'/checkouts/{checkout_id}/discounts', + data=data, + params=params, + timeout=timeout, + ) def create_order( - self, - checkout_id: UUIDLike, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + checkout_id: UUIDLike, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create an order""" - return self._api.post(f'/checkouts/{checkout_id}/orders', params=params, timeout=timeout) + return self._api.post( + f'/checkouts/{checkout_id}/orders', params=params, timeout=timeout + ) diff --git a/src/bigc/resources/currencies_v2.py b/src/bigc/resources/currencies_v2.py index 84a6828..3ce79fb 100644 --- a/src/bigc/resources/currencies_v2.py +++ b/src/bigc/resources/currencies_v2.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV2APIClient @@ -8,22 +9,29 @@ def __init__(self, api: BigCommerceV2APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all currencies""" - return self._api.get_many('/currencies', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/currencies', params=params, timeout=timeout, retries=retries + ) def get( - self, - currency_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + currency_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ): """Get a specific currency by its ID""" - return self._api.get(f'/currencies/{currency_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/currencies/{currency_id}', + params=params, + timeout=timeout, + retries=retries, + ) diff --git a/src/bigc/resources/customer_groups_v2.py b/src/bigc/resources/customer_groups_v2.py index ef529f3..e366bb6 100644 --- a/src/bigc/resources/customer_groups_v2.py +++ b/src/bigc/resources/customer_groups_v2.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV2APIClient @@ -8,47 +9,63 @@ def __init__(self, api: BigCommerceV2APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all customer groups""" - return self._api.get_many('/customer_groups', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/customer_groups', params=params, timeout=timeout, retries=retries + ) def get( - self, - customer_group_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + customer_group_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific customer group by its ID""" - return self._api.get(f'/customer_groups/{customer_group_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/customer_groups/{customer_group_id}', + params=params, + timeout=timeout, + retries=retries, + ) - def create(self, data: dict[str, Any], *, timeout: float | None = None) -> dict[str, Any]: + def create( + self, data: dict[str, Any], *, timeout: float | None = None + ) -> dict[str, Any]: """Create a customer group""" return self._api.post('/customer_groups', data=data, timeout=timeout) def update( - self, - customer_group_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + customer_group_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific customer group by its ID""" - return self._api.put(f'/customer_groups/{customer_group_id}', data=data, timeout=timeout, retries=retries) + return self._api.put( + f'/customer_groups/{customer_group_id}', + data=data, + timeout=timeout, + retries=retries, + ) def delete( - self, - customer_group_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + customer_group_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Delete a specific customer group by its ID""" - return self._api.delete(f'/customer_groups/{customer_group_id}', timeout=timeout, retries=retries) + return self._api.delete( + f'/customer_groups/{customer_group_id}', timeout=timeout, retries=retries + ) diff --git a/src/bigc/resources/customers_v3.py b/src/bigc/resources/customers_v3.py index 0cf0dce..6795be2 100644 --- a/src/bigc/resources/customers_v3.py +++ b/src/bigc/resources/customers_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient from bigc.exceptions import DoesNotExistError, InvalidDataError @@ -9,22 +10,24 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all customers""" - return self._api.get_many('/customers', params=params, timeout=timeout, retries=retries, cursor=True) + return self._api.get_many( + '/customers', params=params, timeout=timeout, retries=retries, cursor=True + ) def get( - self, - customer_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + customer_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific customer by its ID""" params = { @@ -33,35 +36,41 @@ def get( } try: - return self._api.get('/customers', params=params, timeout=timeout, retries=retries)[0] + return self._api.get( + '/customers', params=params, timeout=timeout, retries=retries + )[0] except IndexError: raise DoesNotExistError() from None - def create_many(self, data: list[dict[str, Any]], *, timeout: float | None = None) -> list[dict[str, Any]]: + def create_many( + self, data: list[dict[str, Any]], *, timeout: float | None = None + ) -> list[dict[str, Any]]: """Create many customers""" return self._api.post('/customers', data=data, timeout=timeout) - def create(self, data: dict[str, Any], *, timeout: float | None = None) -> dict[str, Any]: + def create( + self, data: dict[str, Any], *, timeout: float | None = None + ) -> dict[str, Any]: """Create a single customer""" return self.create_many([data], timeout=timeout)[0] def update_many( - self, - data: list[dict[str, Any]], - *, - timeout: float | None = None, - retries: int | None = None, + self, + data: list[dict[str, Any]], + *, + timeout: float | None = None, + retries: int | None = None, ) -> list[dict[str, Any]]: """Update many customers""" return self._api.put('/customers', data=data, timeout=timeout, retries=retries) def update( - self, - customer_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + customer_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a single customer""" data['id'] = customer_id @@ -69,22 +78,22 @@ def update( return self.update_many([data], timeout=timeout, retries=retries)[0] def delete_many( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> None: """Delete many customers""" - self._api.delete(f'/customers', params=params, timeout=timeout, retries=retries) + self._api.delete('/customers', params=params, timeout=timeout, retries=retries) def delete( - self, - customer_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + customer_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> None: """Delete a single customer""" params = { @@ -95,43 +104,49 @@ def delete( self.delete_many(params=params, timeout=timeout, retries=retries) def update_form_fields( - self, - data: list[dict[str, Any]], - *, - timeout: float | None = None, - retries: int | None = None, + self, + data: list[dict[str, Any]], + *, + timeout: float | None = None, + retries: int | None = None, ) -> list[dict[str, Any]]: """Update form-field values""" - return self._api.put('/customers/form-field-values', data=data, timeout=timeout, retries=retries) + return self._api.put( + '/customers/form-field-values', data=data, timeout=timeout, retries=retries + ) def update_form_field( - self, - customer_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + customer_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a single form-field value""" - return self.update_form_fields([{'customer_id': customer_id, **data}], timeout=timeout, retries=retries)[0] + return self.update_form_fields( + [{'customer_id': customer_id, **data}], timeout=timeout, retries=retries + )[0] def all_addresses( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Get all addresses, optionally filtered by a customer's address book""" - return self._api.get_many(f'/customers/addresses', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/customers/addresses', params=params, timeout=timeout, retries=retries + ) def get_address( - self, - address_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + address_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get one address by its ID, from a customer's address book""" params = { @@ -140,15 +155,21 @@ def get_address( } try: - return self._api.get(f'/customers/addresses', params=params, timeout=timeout, retries=retries)[0] + return self._api.get( + '/customers/addresses', params=params, timeout=timeout, retries=retries + )[0] except IndexError: raise DoesNotExistError() from None - def create_addresses(self, data: list[dict[str, Any]], *, timeout: float | None = None) -> list[dict[str, Any]]: + def create_addresses( + self, data: list[dict[str, Any]], *, timeout: float | None = None + ) -> list[dict[str, Any]]: """Create many addresses""" return self._api.post('/customers/addresses', data=data, timeout=timeout) - def create_address(self, data: dict[str, Any], *, timeout: float | None = None) -> dict[str, Any]: + def create_address( + self, data: dict[str, Any], *, timeout: float | None = None + ) -> dict[str, Any]: """Add an address to the customer's address book""" try: return self.create_addresses([data], timeout=timeout)[0] @@ -156,46 +177,52 @@ def create_address(self, data: dict[str, Any], *, timeout: float | None = None) raise InvalidDataError('This address already exists.') from None def update_addresses( - self, - data: list[dict[str, Any]], - *, - timeout: float | None = None, - retries: int | None = None, + self, + data: list[dict[str, Any]], + *, + timeout: float | None = None, + retries: int | None = None, ) -> list[dict[str, Any]]: """Update many addresses""" - return self._api.put('/customers/addresses', data=data, timeout=timeout, retries=retries) + return self._api.put( + '/customers/addresses', data=data, timeout=timeout, retries=retries + ) def update_address( - self, - address_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + address_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update an address by its ID""" try: - return self.update_addresses([{'id': address_id, **data}], timeout=timeout, retries=retries)[0] + return self.update_addresses( + [{'id': address_id, **data}], timeout=timeout, retries=retries + )[0] except IndexError: raise InvalidDataError('This address already exists.') from None def delete_addresses( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> None: """Delete many addresses""" - self._api.delete(f"/customers/addresses", params=params, timeout=timeout, retries=retries) + self._api.delete( + '/customers/addresses', params=params, timeout=timeout, retries=retries + ) def delete_address( - self, - address_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + address_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> None: """Delete an address by its ID""" params = { diff --git a/src/bigc/resources/orders_v2.py b/src/bigc/resources/orders_v2.py index 92b07e2..f1b8740 100644 --- a/src/bigc/resources/orders_v2.py +++ b/src/bigc/resources/orders_v2.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV2APIClient @@ -8,169 +9,225 @@ def __init__(self, api: BigCommerceV2APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all orders""" - return self._api.get_many('/orders', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/orders', params=params, timeout=timeout, retries=retries + ) def get( - self, - order_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get an order by its ID""" - return self._api.get(f'/orders/{order_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/orders/{order_id}', params=params, timeout=timeout, retries=retries + ) def create( - self, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create an order""" return self._api.post('/orders', data=data, params=params, timeout=timeout) def update( - self, - order_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific order by its ID""" - return self._api.put(f'/orders/{order_id}', data=data, timeout=timeout, retries=retries) + return self._api.put( + f'/orders/{order_id}', data=data, timeout=timeout, retries=retries + ) def archive( - self, - order_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> None: """Archive a specific order by its ID""" self._api.delete(f'/orders/{order_id}', timeout=timeout, retries=retries) def all_products( - self, - order_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all order products in an order""" - return self._api.get_many(f'/orders/{order_id}/products', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + f'/orders/{order_id}/products', + params=params, + timeout=timeout, + retries=retries, + ) def get_product( - self, - order_id: int, - product_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + product_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific order product in an order by ID""" - return self._api.get(f'/orders/{order_id}/products/{product_id}', timeout=timeout, retries=retries) + return self._api.get( + f'/orders/{order_id}/products/{product_id}', + timeout=timeout, + retries=retries, + ) def all_shipping_addresses( - self, - order_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all order shipping addresses in an order""" - return self._api.get_many(f'/orders/{order_id}/shipping_addresses', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + f'/orders/{order_id}/shipping_addresses', + params=params, + timeout=timeout, + retries=retries, + ) def get_shipping_address( - self, - order_id: int, - address_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + address_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific shipping address in an order by ID""" - return self._api.get(f'/orders/{order_id}/shipping_addresses/{address_id}', timeout=timeout, retries=retries) + return self._api.get( + f'/orders/{order_id}/shipping_addresses/{address_id}', + timeout=timeout, + retries=retries, + ) def update_shipping_address( - self, - order_id: int, - address_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + address_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific shipping address in an order by ID""" - return self._api.put(f'/orders/{order_id}/shipping_addresses/{address_id}', data=data, timeout=timeout, retries=retries) + return self._api.put( + f'/orders/{order_id}/shipping_addresses/{address_id}', + data=data, + timeout=timeout, + retries=retries, + ) def all_shipments( - self, - order_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Returns all shipments for a specified order""" - return self._api.get_many(f'/orders/{order_id}/shipments', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + f'/orders/{order_id}/shipments', + params=params, + timeout=timeout, + retries=retries, + ) def get_shipment( - self, - order_id: int, - shipment_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + shipment_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a shipment by its ID""" - return self._api.get(f'/orders/{order_id}/shipments/{shipment_id}', timeout=timeout, retries=retries) - - def create_shipment(self, order_id: int, data: dict[str, Any], *, timeout: float | None = None) -> dict[str, Any]: + return self._api.get( + f'/orders/{order_id}/shipments/{shipment_id}', + timeout=timeout, + retries=retries, + ) + + def create_shipment( + self, order_id: int, data: dict[str, Any], *, timeout: float | None = None + ) -> dict[str, Any]: """Creates an order shipment for the specified order""" - return self._api.post(f'/orders/{order_id}/shipments', data=data, timeout=timeout) + return self._api.post( + f'/orders/{order_id}/shipments', data=data, timeout=timeout + ) def update_shipment( - self, - order_id: int, - shipment_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + shipment_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Updates an order shipment for the specified order""" - return self._api.put(f'/orders/{order_id}/shipments/{shipment_id}', data=data, timeout=timeout, retries=retries) + return self._api.put( + f'/orders/{order_id}/shipments/{shipment_id}', + data=data, + timeout=timeout, + retries=retries, + ) def delete_shipment( - self, - order_id: int, - shipment_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + shipment_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> None: """Deletes specific shipment by its ID""" - return self._api.delete(f'/orders/{order_id}/shipments/{shipment_id}', timeout=timeout, retries=retries) + return self._api.delete( + f'/orders/{order_id}/shipments/{shipment_id}', + timeout=timeout, + retries=retries, + ) def all_coupons( - self, - order_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all coupons in an order""" - return self._api.get_many(f'/orders/{order_id}/coupons', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + f'/orders/{order_id}/coupons', + params=params, + timeout=timeout, + retries=retries, + ) diff --git a/src/bigc/resources/orders_v3.py b/src/bigc/resources/orders_v3.py index b1c864d..5fdbf7d 100644 --- a/src/bigc/resources/orders_v3.py +++ b/src/bigc/resources/orders_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient from bigc.exceptions import DoesNotExistError @@ -9,34 +10,44 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def get_refund_quote( - self, - order_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a refund quote for an order by ID""" - return self._api.post(f'/orders/{order_id}/payment_actions/refund_quotes', data=data, timeout=timeout, retries=retries) + return self._api.post( + f'/orders/{order_id}/payment_actions/refund_quotes', + data=data, + timeout=timeout, + retries=retries, + ) def create_refund( - self, - order_id: int, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + order_id: int, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create a refund for an order by ID""" - return self._api.post(f'/orders/{order_id}/payment_actions/refunds', data=data, params=params, timeout=timeout) + return self._api.post( + f'/orders/{order_id}/payment_actions/refunds', + data=data, + params=params, + timeout=timeout, + ) def all_refunds( - self, - order_id: int | None = None, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + order_id: int | None = None, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all refunds, optionally filtered by order""" if order_id: @@ -44,15 +55,17 @@ def all_refunds( else: endpoint = '/orders/payment_actions/refunds' - return self._api.get_many(endpoint, params=params, timeout=timeout, retries=retries) + return self._api.get_many( + endpoint, params=params, timeout=timeout, retries=retries + ) def get_refund( - self, - refund_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + refund_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific refund by its ID""" params = { @@ -61,6 +74,11 @@ def get_refund( } try: - return self._api.get('/orders/payment_actions/refunds', params=params, timeout=timeout, retries=retries)[0] + return self._api.get( + '/orders/payment_actions/refunds', + params=params, + timeout=timeout, + retries=retries, + )[0] except IndexError: raise DoesNotExistError() from None diff --git a/src/bigc/resources/pricing_v3.py b/src/bigc/resources/pricing_v3.py index 15726f5..e2bae7d 100644 --- a/src/bigc/resources/pricing_v3.py +++ b/src/bigc/resources/pricing_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient @@ -8,11 +9,13 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def get_pricing( - self, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for batch product pricing""" - return self._api.post('/pricing/products', data=data, timeout=timeout, retries=retries) + return self._api.post( + '/pricing/products', data=data, timeout=timeout, retries=retries + ) diff --git a/src/bigc/resources/product_variants_v3.py b/src/bigc/resources/product_variants_v3.py index 6cded5e..9052665 100644 --- a/src/bigc/resources/product_variants_v3.py +++ b/src/bigc/resources/product_variants_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient @@ -8,57 +9,78 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def all( - self, - product_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + product_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all variants of a product""" - return self._api.get_many(f'/catalog/products/{product_id}/variants', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + f'/catalog/products/{product_id}/variants', + params=params, + timeout=timeout, + retries=retries, + ) def get( - self, - product_id: int, - variant_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + product_id: int, + variant_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific product variant by ID""" - return self._api.get(f'/catalog/products/{product_id}/variants/{variant_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/catalog/products/{product_id}/variants/{variant_id}', + params=params, + timeout=timeout, + retries=retries, + ) def create( - self, - product_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, + self, + product_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, ) -> dict[str, Any]: """Create a product variant""" - return self._api.post(f'/catalog/products/{product_id}/variants', data=data, timeout=timeout) + return self._api.post( + f'/catalog/products/{product_id}/variants', data=data, timeout=timeout + ) def update( - self, - product_id: int, - variant_id: int, - data: dict[str, Any], - *, - timeout: float | None = None, - retries: int | None = None, + self, + product_id: int, + variant_id: int, + data: dict[str, Any], + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific product variant by its ID""" - return self._api.put(f'/catalog/products/{product_id}/variants/{variant_id}', data=data, timeout=timeout, retries=retries) + return self._api.put( + f'/catalog/products/{product_id}/variants/{variant_id}', + data=data, + timeout=timeout, + retries=retries, + ) def delete( - self, - product_id: int, - variant_id: int, - *, - timeout: float | None = None, - retries: int | None = None, + self, + product_id: int, + variant_id: int, + *, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Delete a specific product variant by its ID""" - return self._api.delete(f'/catalog/products/{product_id}/variants/{variant_id}', timeout=timeout, retries=retries) + return self._api.delete( + f'/catalog/products/{product_id}/variants/{variant_id}', + timeout=timeout, + retries=retries, + ) diff --git a/src/bigc/resources/products_v3.py b/src/bigc/resources/products_v3.py index 3e38020..d558bb6 100644 --- a/src/bigc/resources/products_v3.py +++ b/src/bigc/resources/products_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient @@ -8,48 +9,71 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all products""" - return self._api.get_many('/catalog/products', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/catalog/products', params=params, timeout=timeout, retries=retries + ) def get( - self, - product_id: int, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + product_id: int, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Get a specific product by its ID""" - return self._api.get(f'/catalog/products/{product_id}', params=params, timeout=timeout, retries=retries) + return self._api.get( + f'/catalog/products/{product_id}', + params=params, + timeout=timeout, + retries=retries, + ) def create( - self, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create a product""" - return self._api.post('/catalog/products', data=data, params=params, timeout=timeout) + return self._api.post( + '/catalog/products', data=data, params=params, timeout=timeout + ) def update( - self, - product_id: int, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + product_id: int, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific product by its ID""" - return self._api.put(f'/catalog/products/{product_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/catalog/products/{product_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) - def delete(self, product_id: int, *, timeout: float | None = None, retries: int | None = None) -> dict[str, Any]: + def delete( + self, + product_id: int, + *, + timeout: float | None = None, + retries: int | None = None, + ) -> dict[str, Any]: """Delete a specific product by its ID""" - return self._api.delete(f'/catalog/products/{product_id}', timeout=timeout, retries=retries) + return self._api.delete( + f'/catalog/products/{product_id}', timeout=timeout, retries=retries + ) diff --git a/src/bigc/resources/webhooks_v3.py b/src/bigc/resources/webhooks_v3.py index 5655a4d..49221f9 100644 --- a/src/bigc/resources/webhooks_v3.py +++ b/src/bigc/resources/webhooks_v3.py @@ -1,4 +1,5 @@ -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any from bigc.api_client import BigCommerceV3APIClient @@ -8,41 +9,63 @@ def __init__(self, api: BigCommerceV3APIClient): self._api = api def all( - self, - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> Iterator[dict[str, Any]]: """Return an iterator for all webhooks""" - return self._api.get_many('/hooks', params=params, timeout=timeout, retries=retries) + return self._api.get_many( + '/hooks', params=params, timeout=timeout, retries=retries + ) - def get(self, webhook_id: int, *, timeout: float | None = None, retries: int | None = None) -> dict[str, Any]: + def get( + self, + webhook_id: int, + *, + timeout: float | None = None, + retries: int | None = None, + ) -> dict[str, Any]: """Get a specific webhook by its ID""" return self._api.get(f'/hooks/{webhook_id}', timeout=timeout, retries=retries) def create( - self, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, + self, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, ) -> dict[str, Any]: """Create a webhook under a specific scope""" return self._api.post('/hooks', data=data, params=params, timeout=timeout) def update( - self, - webhook_id: int, - data: dict[str, Any], - *, - params: dict[str, Any] | None = None, - timeout: float | None = None, - retries: int | None = None, + self, + webhook_id: int, + data: dict[str, Any], + *, + params: dict[str, Any] | None = None, + timeout: float | None = None, + retries: int | None = None, ) -> dict[str, Any]: """Update a specific webhook by its ID""" - return self._api.put(f'/hooks/{webhook_id}', data=data, params=params, timeout=timeout, retries=retries) + return self._api.put( + f'/hooks/{webhook_id}', + data=data, + params=params, + timeout=timeout, + retries=retries, + ) - def delete(self, webhook_id: int, *, timeout: float | None = None, retries: int | None = None) -> dict[str, Any]: + def delete( + self, + webhook_id: int, + *, + timeout: float | None = None, + retries: int | None = None, + ) -> dict[str, Any]: """Delete a specific webhook by its ID""" - return self._api.delete(f'/hooks/{webhook_id}', timeout=timeout, retries=retries) + return self._api.delete( + f'/hooks/{webhook_id}', timeout=timeout, retries=retries + ) diff --git a/tests/test_api.py b/tests/test_api.py index 2e22dd2..cf6759d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -13,7 +13,10 @@ def test_each_thread_gets_its_own_session(self): api = BigCommerceAPI('store_hash', 'access_token') sessions = [] - threads = [threading.Thread(target=lambda: sessions.append(api.api_v2._session)) for _ in range(8)] + threads = [ + threading.Thread(target=lambda: sessions.append(api.api_v2._session)) + for _ in range(8) + ] for thread in threads: thread.start() for thread in threads: diff --git a/tests/test_api_client.py b/tests/test_api_client.py index 9824ade..7666455 100644 --- a/tests/test_api_client.py +++ b/tests/test_api_client.py @@ -1,5 +1,6 @@ -from typing import Any, Iterator -from unittest.mock import create_autospec, MagicMock, Mock +from collections.abc import Iterator +from typing import Any +from unittest.mock import MagicMock, create_autospec import pytest import requests @@ -20,7 +21,9 @@ def get_many( raise NotImplementedError def _prepare_url(self, path: str) -> str: - return f'https://api.example.com/stores/{self.store_hash}/test/{path.lstrip("/")}' + return ( + f'https://api.example.com/stores/{self.store_hash}/test/{path.lstrip("/")}' + ) @pytest.fixture @@ -42,7 +45,9 @@ def request_mock(monkeypatch): class TestRequest: - def test_retry_for_always_failing_endpoint(self, request_mock, dummy_request_client): + def test_retry_for_always_failing_endpoint( + self, request_mock, dummy_request_client + ): request_mock.side_effect = requests.RequestException() with pytest.raises(BigCommerceNetworkError): @@ -51,8 +56,14 @@ def test_retry_for_always_failing_endpoint(self, request_mock, dummy_request_cli assert request_mock.call_count == 3 @pytest.mark.parametrize('retries', [2, 3]) - def test_retry_eventually_succeeds(self, request_mock, dummy_request_client, retries): - request_mock.side_effect = (requests.RequestException(), requests.RequestException(), request_mock.return_value) + def test_retry_eventually_succeeds( + self, request_mock, dummy_request_client, retries + ): + request_mock.side_effect = ( + requests.RequestException(), + requests.RequestException(), + request_mock.return_value, + ) dummy_request_client.request('GET', '/test', retries=retries) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index b27c7cf..9f4ca3e 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -13,47 +13,57 @@ def test_str(self): def test_str_default_message(self): assert str(BigCommerceException()) == 'Request to BigCommerce failed.' assert str(DoesNotExistError()) == 'The requested entity does not exist.' - assert str(InternalServerError()) == 'An error has occurred within the BigCommerce server.' + assert ( + str(InternalServerError()) + == 'An error has occurred within the BigCommerce server.' + ) - @pytest.mark.parametrize('status_code, exc_class', [ - (301, BigCommerceException), - (400, BadRequestError), - (401, UnauthorizedError), - (403, ForbiddenError), - (404, DoesNotExistError), - (405, BigCommerceClientError), - (406, BigCommerceClientError), - (409, ConflictError), - (413, EntityTooLargeError), - (415, BigCommerceClientError), - (422, InvalidDataError), - (423, LockedError), - (429, TooManyRequestsError), - (499, BigCommerceClientError), - (500, InternalServerError), - (501, BigCommerceServerError), - (502, BadGatewayError), - (503, ServiceUnavailableError), - (504, GatewayTimeoutError), - (507, InsufficientStorageError), - ]) + @pytest.mark.parametrize( + 'status_code, exc_class', + [ + (301, BigCommerceException), + (400, BadRequestError), + (401, UnauthorizedError), + (403, ForbiddenError), + (404, DoesNotExistError), + (405, BigCommerceClientError), + (406, BigCommerceClientError), + (409, ConflictError), + (413, EntityTooLargeError), + (415, BigCommerceClientError), + (422, InvalidDataError), + (423, LockedError), + (429, TooManyRequestsError), + (499, BigCommerceClientError), + (500, InternalServerError), + (501, BigCommerceServerError), + (502, BadGatewayError), + (503, ServiceUnavailableError), + (504, GatewayTimeoutError), + (507, InsufficientStorageError), + ], + ) def test_get_exc_class_for_status_code(self, status_code, exc_class): - assert BigCommerceException.get_exc_class_for_status_code(status_code) is exc_class + assert ( + BigCommerceException.get_exc_class_for_status_code(status_code) is exc_class + ) class TestBigCommerceExceptionExtractErrorMessage: def test_parse_object_style_message(self): - message, errors = BigCommerceException.extract_error_message({ - 'status': 422, - 'title': 'Missing Required Fields', - 'type': 'https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes', - 'errors': { - 'name': 'Please provide a name.', - 'price': 'Please provide a price.', - 'type': 'Please provide a type.', - 'weight': 'Please provide a weight.', - }, - }) + message, errors = BigCommerceException.extract_error_message( + { + 'status': 422, + 'title': 'Missing Required Fields', + 'type': 'https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes', + 'errors': { + 'name': 'Please provide a name.', + 'price': 'Please provide a price.', + 'type': 'Please provide a type.', + 'weight': 'Please provide a weight.', + }, + } + ) assert message == 'Missing Required Fields' assert errors == { @@ -64,31 +74,40 @@ def test_parse_object_style_message(self): } def test_parse_object_style_message_without_errors(self): - message, errors = BigCommerceException.extract_error_message({ - 'status': 409, - 'title': 'Your checkout could not be processed because some details have changed.', - 'type': 'https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes' - }) + message, errors = BigCommerceException.extract_error_message( + { + 'status': 409, + 'title': 'Your checkout could not be processed because some details have changed.', + 'type': 'https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes', + } + ) - assert message == 'Your checkout could not be processed because some details have changed.' + assert ( + message + == 'Your checkout could not be processed because some details have changed.' + ) assert errors is None def test_parse_object_style_message_without_title(self): - message, errors = BigCommerceException.extract_error_message({ - 'status': 404, - 'type': 'https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes', - }) + message, errors = BigCommerceException.extract_error_message( + { + 'status': 404, + 'type': 'https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes', + } + ) assert message is None assert errors is None def test_parse_array_style_message(self): - message, errors = BigCommerceException.extract_error_message([ - { - 'status': 400, - 'message': "The required field 'name' was not supplied.", - }, - ]) + message, errors = BigCommerceException.extract_error_message( + [ + { + 'status': 400, + 'message': "The required field 'name' was not supplied.", + }, + ] + ) assert message == "The required field 'name' was not supplied." assert errors is None diff --git a/tests/test_utils.py b/tests/test_utils.py index cd32db1..eec2eca 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,25 +1,45 @@ from datetime import datetime, timedelta, timezone + import pytest + from bigc.utils import parse_rfc2822_date TZ_UTC = timezone.utc class TestParseRfc2822Date: - @pytest.mark.parametrize('test_input,expected', [ - ('Mon, 01 Jan 1900 00:00:00 +0000', datetime(1900, 1, 1, tzinfo=TZ_UTC)), - ('1 Jan 1900 00:00 +0000', datetime(1900, 1, 1, tzinfo=TZ_UTC)), - ('Sun, 20 Jul 1969 20:17:40 +0000', datetime(1969, 7, 20, 20, 17, 40, tzinfo=TZ_UTC)), - ('Tue, 05 Mar 2019 21:40:11 +0000', datetime(2019, 3, 5, 21, 40, 11, tzinfo=TZ_UTC)), - ]) + @pytest.mark.parametrize( + 'test_input,expected', + [ + ('Mon, 01 Jan 1900 00:00:00 +0000', datetime(1900, 1, 1, tzinfo=TZ_UTC)), + ('1 Jan 1900 00:00 +0000', datetime(1900, 1, 1, tzinfo=TZ_UTC)), + ( + 'Sun, 20 Jul 1969 20:17:40 +0000', + datetime(1969, 7, 20, 20, 17, 40, tzinfo=TZ_UTC), + ), + ( + 'Tue, 05 Mar 2019 21:40:11 +0000', + datetime(2019, 3, 5, 21, 40, 11, tzinfo=TZ_UTC), + ), + ], + ) def test_parse_utc(self, test_input, expected): assert parse_rfc2822_date(test_input) == expected - @pytest.mark.parametrize('test_input,expected', [ - ('Sat, 01 Jan 2000 0:00:00 +0000', datetime(2000, 1, 1, tzinfo=TZ_UTC)), - ('Sat, 01 Jan 2000 0:00:00 -0400', datetime(2000, 1, 1, tzinfo=timezone(-timedelta(hours=4)))), - ('Sat, 01 Jan 2000 0:00:00 +0900', datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=9)))), - ]) + @pytest.mark.parametrize( + 'test_input,expected', + [ + ('Sat, 01 Jan 2000 0:00:00 +0000', datetime(2000, 1, 1, tzinfo=TZ_UTC)), + ( + 'Sat, 01 Jan 2000 0:00:00 -0400', + datetime(2000, 1, 1, tzinfo=timezone(-timedelta(hours=4))), + ), + ( + 'Sat, 01 Jan 2000 0:00:00 +0900', + datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=9))), + ), + ], + ) def test_parse_tz(self, test_input, expected): assert parse_rfc2822_date(test_input) == expected assert parse_rfc2822_date(test_input).tzinfo == TZ_UTC From 06fb552ac984bbb615e94e9e8632927e147e3c5a Mon Sep 17 00:00:00 2001 From: Ryan Thomson Date: Mon, 17 Aug 2026 09:54:39 -0400 Subject: [PATCH 3/4] Add .git-blame-ignore-revs --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..e2ba9b0 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# .git-blame-ignore-revs +# Format with Ruff +945e183c36d109e10d9699bcc40af6a431a0a7ec From 6adf4aee95a2b25b2e782fc611ea6794a526a5db Mon Sep 17 00:00:00 2001 From: Ryan Thomson Date: Mon, 17 Aug 2026 10:09:07 -0400 Subject: [PATCH 4/4] Add Ruff checks to GitHub actions --- .github/workflows/python-checks.yml | 47 +++++++++++++++++++++++++++++ .github/workflows/python-tests.yml | 27 ----------------- 2 files changed, 47 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/python-checks.yml delete mode 100644 .github/workflows/python-tests.yml diff --git a/.github/workflows/python-checks.yml b/.github/workflows/python-checks.yml new file mode 100644 index 0000000..eaf33be --- /dev/null +++ b/.github/workflows/python-checks.yml @@ -0,0 +1,47 @@ +name: Python tests + +on: [ push, pull_request ] + +jobs: + run-tests: + name: "Run tests" + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] + + steps: + - uses: actions/checkout@v7 + + - name: Install uv and set up Python + uses: astral-sh/setup-uv@v10.0.1 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: uv sync --locked + + - name: Test with pytest + run: uv run pytest + + run-static-checks: + name: "Run static checks" + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v7 + + - name: Install uv + uses: astral-sh/setup-uv@v10.0.1 + + - name: Install dependencies + run: uv sync --locked --dev + + - name: Run linter + run: uv run ruff check --output-format github + + - name: Check formatting + run: uv run ruff format --check --output-format github diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml deleted file mode 100644 index d449894..0000000 --- a/.github/workflows/python-tests.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Python tests - -on: [ push, pull_request ] - -jobs: - run-tests: - name: "Run tests" - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - python-version: [ "3.10", "3.11", "3.12", "3.13" ] - - steps: - - uses: actions/checkout@v5 - - - name: Install uv and set up Python - uses: astral-sh/setup-uv@v7 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: uv sync --locked - - - name: Test with pytest - run: uv run pytest