From dea467eeab1d1e23fb30fdc31b27a8b9b4f59f27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 05:36:29 +0000 Subject: [PATCH 1/9] chore(deps): update pydantic requirement from ^1.8.0 to >=1.8,<3.0 Updates the requirements on [pydantic](https://github.com/pydantic/pydantic) to permit the latest version. - [Release notes](https://github.com/pydantic/pydantic/releases) - [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md) - [Commits](https://github.com/pydantic/pydantic/compare/v1.8...v2.8.2) --- updated-dependencies: - dependency-name: pydantic dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a4f6448..cb41a9d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ include = ["src/ikea_api/py.typed"] python = "^3.8" typing-extensions = {version = "^4.0.0", python = "<3.10"} requests = {version = "*", optional = true} -pydantic = {version = "^1.8.0", optional = true} +pydantic = {version = ">=1.8,<3.0", optional = true} httpx = {version = "^0.23", optional = true} [tool.poetry.dev-dependencies] From dd82e00a25b068f8ae068dd01bf8acfb7c8f56ec Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:43:56 +0300 Subject: [PATCH 2/9] Use pydantic 2.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index cb41a9d..d83e9e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ include = ["src/ikea_api/py.typed"] python = "^3.8" typing-extensions = {version = "^4.0.0", python = "<3.10"} requests = {version = "*", optional = true} -pydantic = {version = ">=1.8,<3.0", optional = true} +pydantic = {version = ">=2.0,<3.0", optional = true} httpx = {version = "^0.23", optional = true} [tool.poetry.dev-dependencies] From 93c3ff21170bd4ad283742e69a4331f825e72cdd Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:44:13 +0300 Subject: [PATCH 3/9] Update --- src/ikea_api/wrappers/parsers/ingka_items.py | 2 +- src/ikea_api/wrappers/parsers/item_base.py | 28 +++++++++---------- .../wrappers/parsers/order_capture.py | 4 +-- src/ikea_api/wrappers/parsers/pip_item.py | 2 +- src/ikea_api/wrappers/parsers/purchases.py | 6 ++-- src/ikea_api/wrappers/wrappers.py | 2 +- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/ikea_api/wrappers/parsers/ingka_items.py b/src/ikea_api/wrappers/parsers/ingka_items.py index aeea13b..42e8372 100644 --- a/src/ikea_api/wrappers/parsers/ingka_items.py +++ b/src/ikea_api/wrappers/parsers/ingka_items.py @@ -178,6 +178,6 @@ def parse_item(constants: Constants, item: ResponseIngkaItem) -> types.IngkaItem def parse_ingka_items( constants: Constants, response: dict[str, Any] ) -> Iterable[types.IngkaItem]: - parsed_resp = ResponseIngkaItems(**response) + parsed_resp = ResponseIngkaItems.model_validate(response) for item in parsed_resp.data: yield parse_item(constants, item) diff --git a/src/ikea_api/wrappers/parsers/item_base.py b/src/ikea_api/wrappers/parsers/item_base.py index 89757f1..897cd87 100644 --- a/src/ikea_api/wrappers/parsers/item_base.py +++ b/src/ikea_api/wrappers/parsers/item_base.py @@ -1,25 +1,23 @@ from typing import Any, Literal -from ikea_api.utils import parse_item_codes +from pydantic import BeforeValidator +from typing_extensions import Annotated +from ikea_api.utils import parse_item_codes -class ItemCode(str): - @classmethod - def __get_validators__(cls): - yield cls.validate - @classmethod - def validate(cls, v: Any): - if isinstance(v, int): - v = str(v) - if isinstance(v, str): - parsed_item_codes = parse_item_codes(v) - if len(parsed_item_codes) != 1: - raise ValueError("invalid item code format") - return parsed_item_codes[0] - raise TypeError("string required") +def validate_item_code(value: Any) -> str: + if isinstance(value, int): + value = str(value) + if isinstance(value, str): + parsed_item_codes = parse_item_codes(value) + if len(parsed_item_codes) != 1: + raise ValueError("invalid item code format") + return parsed_item_codes[0] + raise TypeError("string required") +ItemCode = Annotated[str, BeforeValidator(validate_item_code)] ItemType = Literal["ART", "SPR"] diff --git a/src/ikea_api/wrappers/parsers/order_capture.py b/src/ikea_api/wrappers/parsers/order_capture.py index d6b6ac1..004b877 100644 --- a/src/ikea_api/wrappers/parsers/order_capture.py +++ b/src/ikea_api/wrappers/parsers/order_capture.py @@ -148,7 +148,7 @@ class HomeDeliveryServicesResponse(BaseModel): def parse_home_delivery_services( constants: Constants, response: dict[str, Any] ) -> list[types.DeliveryService]: - parsed_response = HomeDeliveryServicesResponse(**response) + parsed_response = HomeDeliveryServicesResponse.model_validate(response) res: list[types.DeliveryService] = [] if not parsed_response.possibleDeliveryServices: @@ -230,7 +230,7 @@ def get_service_provider(constants: Constants, pickup_point: PickUpPoint) -> str def parse_collect_delivery_services( constants: Constants, response: dict[str, Any] ) -> list[types.DeliveryService]: - parsed_response = CollectDeliveryServicesResponse(**response) + parsed_response = CollectDeliveryServicesResponse.model_validate(response) res: list[types.DeliveryService] = [] if not parsed_response.possibleDeliveryServices: diff --git a/src/ikea_api/wrappers/parsers/pip_item.py b/src/ikea_api/wrappers/parsers/pip_item.py index 894e752..3da8d83 100644 --- a/src/ikea_api/wrappers/parsers/pip_item.py +++ b/src/ikea_api/wrappers/parsers/pip_item.py @@ -37,7 +37,7 @@ def get_category_name_and_url(catalog_refs: CatalogRefs): def parse_pip_item(response: dict[str, Any]) -> types.PipItem | None: if not response: return - parsed_item = ResponsePipItem(**response) + parsed_item = ResponsePipItem.model_validate(response) category_name, category_url = get_category_name_and_url(parsed_item.catalogRefs) return types.PipItem( item_code=parsed_item.id, diff --git a/src/ikea_api/wrappers/parsers/purchases.py b/src/ikea_api/wrappers/parsers/purchases.py index 21841cc..deeb2c3 100644 --- a/src/ikea_api/wrappers/parsers/purchases.py +++ b/src/ikea_api/wrappers/parsers/purchases.py @@ -85,7 +85,7 @@ class ResponseHistory(BaseModel): def parse_status_banner_order(response: dict[str, Any]) -> types.StatusBannerOrder: - order = ResponseStatusBanner(**response) + order = ResponseStatusBanner.model_validate(response) return types.StatusBannerOrder( purchase_date=order.data.order.dateAndTime.date, delivery_date=order.data.order.deliveryMethods[ @@ -95,7 +95,7 @@ def parse_status_banner_order(response: dict[str, Any]) -> types.StatusBannerOrd def parse_costs_order(response: dict[str, Any]) -> types.CostsOrder: - order = ResponseCosts(**response) + order = ResponseCosts.model_validate(response) costs = order.data.order.costs return types.CostsOrder( delivery_cost=costs.delivery.value, total_cost=costs.total.value @@ -109,7 +109,7 @@ def get_history_datetime(item: HistoryItem) -> str: def parse_history( constants: Constants, response: dict[str, Any] ) -> list[types.PurchaseHistoryItem]: - history = ResponseHistory(**response) + history = ResponseHistory.model_validate(response) return [ types.PurchaseHistoryItem( id=i.id, diff --git a/src/ikea_api/wrappers/wrappers.py b/src/ikea_api/wrappers/wrappers.py index ded90e5..48e1ae7 100644 --- a/src/ikea_api/wrappers/wrappers.py +++ b/src/ikea_api/wrappers/wrappers.py @@ -68,7 +68,7 @@ def add_items_to_cart(cart: Cart, items: dict[str, int]) -> types.CannotAddItems break except GraphQLError as exc: for error_dict in exc.errors: - error = _CartErrorRef(**error_dict) + error = _CartErrorRef.model_validate(error_dict) if error.extensions.code != "INVALID_ITEM_NUMBER": continue if not error.extensions.data: From e10c6bceed3aaaade753028c23d94d1d2a539a38 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:45:52 +0300 Subject: [PATCH 4/9] Update --- src/ikea_api/wrappers/parsers/order_capture.py | 14 ++++++-------- src/ikea_api/wrappers/parsers/pip_item.py | 2 +- src/ikea_api/wrappers/wrappers.py | 4 ++-- tests/wrappers/parsers/test_item_base.py | 9 ++++----- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/ikea_api/wrappers/parsers/order_capture.py b/src/ikea_api/wrappers/parsers/order_capture.py index 004b877..6684842 100644 --- a/src/ikea_api/wrappers/parsers/order_capture.py +++ b/src/ikea_api/wrappers/parsers/order_capture.py @@ -3,7 +3,11 @@ from datetime import datetime from typing import Any, List, Optional -from pydantic import BaseModel, validator # pyright: ignore[reportUnknownVariableType] +from pydantic import ( # pyright: ignore[reportUnknownVariableType] + AfterValidator, + BaseModel, +) +from typing_extensions import Annotated from ikea_api.constants import Constants from ikea_api.utils import translate_from_dict @@ -57,13 +61,7 @@ class TimeWindows(BaseModel): class SelectableInfo(BaseModel): - selectable: bool - - @validator( - "selectable", pre=True - ) # pyright: ignore[reportUntypedFunctionDecorator] - def validate_selectable(cls, v: Any) -> Any: - return v == "YES" + selectable: Annotated[bool, AfterValidator(lambda value: value == "YES")] class Metadata(BaseModel): diff --git a/src/ikea_api/wrappers/parsers/pip_item.py b/src/ikea_api/wrappers/parsers/pip_item.py index 3da8d83..c599f3a 100644 --- a/src/ikea_api/wrappers/parsers/pip_item.py +++ b/src/ikea_api/wrappers/parsers/pip_item.py @@ -42,7 +42,7 @@ def parse_pip_item(response: dict[str, Any]) -> types.PipItem | None: return types.PipItem( item_code=parsed_item.id, price=parsed_item.priceNumeral, - url=parsed_item.pipUrl, + url=str(parsed_item.pipUrl), category_name=category_name, category_url=category_url, ) diff --git a/src/ikea_api/wrappers/wrappers.py b/src/ikea_api/wrappers/wrappers.py index 48e1ae7..ce0b06b 100644 --- a/src/ikea_api/wrappers/wrappers.py +++ b/src/ikea_api/wrappers/wrappers.py @@ -39,8 +39,8 @@ def get_purchase_info( ) status_banner, costs = run_with_requests(endpoint) return types.PurchaseInfo( - **parse_status_banner_order(status_banner).dict(), - **parse_costs_order(costs).dict(), + **parse_status_banner_order(status_banner).model_dump(), + **parse_costs_order(costs).model_dump(), ) diff --git a/tests/wrappers/parsers/test_item_base.py b/tests/wrappers/parsers/test_item_base.py index dddf3c1..4a3c9a9 100644 --- a/tests/wrappers/parsers/test_item_base.py +++ b/tests/wrappers/parsers/test_item_base.py @@ -1,27 +1,26 @@ from __future__ import annotations import pytest - from ikea_api.wrappers.parsers.item_base import ( - ItemCode, ItemType, get_is_combination_from_item_type, + validate_item_code, ) def test_item_code_validator_value_error(): with pytest.raises(ValueError, match="invalid item code format"): - assert ItemCode.validate("11111.11") == "11111111" + assert validate_item_code("11111.11") == "11111111" def test_item_code_validator_type_error(): with pytest.raises(TypeError, match="string required"): - ItemCode.validate({}) + validate_item_code({}) @pytest.mark.parametrize("v", ("11111111", "111.111.11", "111-111-11", 11111111)) def test_item_code_validator_passes(v: str | int): - assert ItemCode.validate(v) == "11111111" + assert validate_item_code(v) == "11111111" @pytest.mark.parametrize( From 7b2f08dda4d7fa7a918a6d391059dc988e251b41 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:53:15 +0300 Subject: [PATCH 5/9] Run bump-pydantic --- src/ikea_api/wrappers/parsers/ingka_items.py | 12 +++---- .../wrappers/parsers/order_capture.py | 34 +++++++++---------- src/ikea_api/wrappers/parsers/pip_item.py | 2 +- src/ikea_api/wrappers/parsers/purchases.py | 2 +- src/ikea_api/wrappers/types.py | 18 +++++----- src/ikea_api/wrappers/wrappers.py | 2 +- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/ikea_api/wrappers/parsers/ingka_items.py b/src/ikea_api/wrappers/parsers/ingka_items.py index 42e8372..ee19f37 100644 --- a/src/ikea_api/wrappers/parsers/ingka_items.py +++ b/src/ikea_api/wrappers/parsers/ingka_items.py @@ -48,17 +48,17 @@ class ReferenceMeasurements(BaseModel): class Measurements(BaseModel): - referenceMeasurements: Optional[List[ReferenceMeasurements]] + referenceMeasurements: Optional[List[ReferenceMeasurements]] = None class LocalisedCommunication(BaseModel): languageCode: str - packageMeasurements: Optional[List[PackageMeasurement]] - media: Optional[List[Media]] + packageMeasurements: Optional[List[PackageMeasurement]] = None + media: Optional[List[Media]] = None productName: str productType: ProductType - validDesign: Optional[ValidDesign] - measurements: Optional[Measurements] + validDesign: Optional[ValidDesign] = None + measurements: Optional[Measurements] = None class ChildItem(BaseModel): @@ -69,7 +69,7 @@ class ChildItem(BaseModel): class ResponseIngkaItem(BaseModel): itemKey: ItemKey localisedCommunications: List[LocalisedCommunication] - childItems: Optional[List[ChildItem]] + childItems: Optional[List[ChildItem]] = None class ResponseIngkaItems(BaseModel): diff --git a/src/ikea_api/wrappers/parsers/order_capture.py b/src/ikea_api/wrappers/parsers/order_capture.py index 6684842..1e8b11a 100644 --- a/src/ikea_api/wrappers/parsers/order_capture.py +++ b/src/ikea_api/wrappers/parsers/order_capture.py @@ -1,6 +1,6 @@ from __future__ import annotations -from datetime import datetime +from datetime import date, datetime from typing import Any, List, Optional from pydantic import ( # pyright: ignore[reportUnknownVariableType] @@ -57,7 +57,7 @@ class EarliestPossibleSlot(BaseModel): class TimeWindows(BaseModel): - earliestPossibleSlot: Optional[EarliestPossibleSlot] + earliestPossibleSlot: Optional[EarliestPossibleSlot] = None class SelectableInfo(BaseModel): @@ -73,13 +73,13 @@ class UnavailableItem(BaseModel): availableQuantity: int -def get_date(deliveries: list[HomeDelivery] | None) -> datetime | None: +def get_date(deliveries: list[HomeDelivery] | None) -> date | None: if not deliveries: return for delivery in deliveries: if delivery.timeWindows and delivery.timeWindows.earliestPossibleSlot: - return delivery.timeWindows.earliestPossibleSlot.fromDateTime + return delivery.timeWindows.earliestPossibleSlot.fromDateTime.date() def get_type( @@ -119,7 +119,7 @@ def get_unavailable_items( class HomeDelivery(BaseModel): type: str - timeWindows: Optional[TimeWindows] + timeWindows: Optional[TimeWindows] = None class HomePossibleDeliveries(BaseModel): @@ -129,10 +129,10 @@ class HomePossibleDeliveries(BaseModel): class HomeDeliveryService(BaseModel): metadata: Metadata fulfillmentMethodType: str - solution: Optional[str] - solutionPrice: Optional[SolutionPrice] - possibleDeliveries: Optional[HomePossibleDeliveries] - unavailableItems: Optional[List[UnavailableItem]] + solution: Optional[str] = None + solutionPrice: Optional[SolutionPrice] = None + possibleDeliveries: Optional[HomePossibleDeliveries] = None + unavailableItems: Optional[List[UnavailableItem]] = None class HomePossibleDeliveryServices(BaseModel): @@ -140,7 +140,7 @@ class HomePossibleDeliveryServices(BaseModel): class HomeDeliveryServicesResponse(BaseModel): - possibleDeliveryServices: Optional[HomePossibleDeliveryServices] + possibleDeliveryServices: Optional[HomePossibleDeliveryServices] = None def parse_home_delivery_services( @@ -182,8 +182,8 @@ def parse_home_delivery_services( class PickUpPoint(BaseModel): metadata: Metadata - timeWindows: Optional[TimeWindows] - identifier: Optional[str] + timeWindows: Optional[TimeWindows] = None + identifier: Optional[str] = None class PossiblePickUpPoints(BaseModel): @@ -201,10 +201,10 @@ class CollectPossibleDeliveries(BaseModel): class CollectDeliveryService(BaseModel): fulfillmentMethodType: str - solution: Optional[str] - solutionPrice: Optional[SolutionPrice] - possibleDeliveries: Optional[CollectPossibleDeliveries] - unavailableItems: Optional[List[UnavailableItem]] + solution: Optional[str] = None + solutionPrice: Optional[SolutionPrice] = None + possibleDeliveries: Optional[CollectPossibleDeliveries] = None + unavailableItems: Optional[List[UnavailableItem]] = None class CollectPossibleDeliveryServices(BaseModel): @@ -212,7 +212,7 @@ class CollectPossibleDeliveryServices(BaseModel): class CollectDeliveryServicesResponse(BaseModel): - possibleDeliveryServices: Optional[CollectPossibleDeliveryServices] + possibleDeliveryServices: Optional[CollectPossibleDeliveryServices] = None def get_service_provider(constants: Constants, pickup_point: PickUpPoint) -> str | None: diff --git a/src/ikea_api/wrappers/parsers/pip_item.py b/src/ikea_api/wrappers/parsers/pip_item.py index c599f3a..206c767 100644 --- a/src/ikea_api/wrappers/parsers/pip_item.py +++ b/src/ikea_api/wrappers/parsers/pip_item.py @@ -18,7 +18,7 @@ class CatalogRef(BaseModel): class CatalogRefs(BaseModel): - products: Optional[CatalogRef] + products: Optional[CatalogRef] = None class ResponsePipItem(BaseModel): diff --git a/src/ikea_api/wrappers/parsers/purchases.py b/src/ikea_api/wrappers/parsers/purchases.py index deeb2c3..fee93cb 100644 --- a/src/ikea_api/wrappers/parsers/purchases.py +++ b/src/ikea_api/wrappers/parsers/purchases.py @@ -65,7 +65,7 @@ class HistoryDateAndTime(BaseModel): class HistoryTotalCost(BaseModel): - value: Optional[int] + value: Optional[int] = None class HistoryItem(BaseModel): diff --git a/src/ikea_api/wrappers/types.py b/src/ikea_api/wrappers/types.py index a01065a..577d0f2 100644 --- a/src/ikea_api/wrappers/types.py +++ b/src/ikea_api/wrappers/types.py @@ -7,7 +7,7 @@ class ChildItem(BaseModel): - name: Optional[str] + name: Optional[str] = None item_code: str weight: float qty: int @@ -17,20 +17,20 @@ class ParsedItem(BaseModel): is_combination: bool item_code: str name: str - image_url: Optional[str] + image_url: Optional[str] = None weight: float child_items: List[ChildItem] price: int url: str - category_name: Optional[str] - category_url: Optional[HttpUrl] + category_name: Optional[str] = None + category_url: Optional[HttpUrl] = None class IngkaItem(BaseModel): is_combination: bool item_code: str name: str - image_url: Optional[str] + image_url: Optional[str] = None weight: float child_items: List[ChildItem] @@ -39,8 +39,8 @@ class PipItem(BaseModel): item_code: str price: int url: str - category_name: Optional[str] - category_url: Optional[HttpUrl] + category_name: Optional[str] = None + category_url: Optional[HttpUrl] = None class UnavailableItem(BaseModel): @@ -50,10 +50,10 @@ class UnavailableItem(BaseModel): class DeliveryService(BaseModel): is_available: bool - date: Optional[datetime.date] + date: Optional[datetime.date] = None type: str price: int - service_provider: Optional[str] + service_provider: Optional[str] = None unavailable_items: List[UnavailableItem] diff --git a/src/ikea_api/wrappers/wrappers.py b/src/ikea_api/wrappers/wrappers.py index ce0b06b..d97dd8f 100644 --- a/src/ikea_api/wrappers/wrappers.py +++ b/src/ikea_api/wrappers/wrappers.py @@ -50,7 +50,7 @@ class _ExtensionsData(BaseModel): class _Extensions(BaseModel): code: str - data: Optional[_ExtensionsData] + data: Optional[_ExtensionsData] = None class _CartErrorRef(BaseModel): From 76eee5e21b66a570e4c0f69a89f42a26ccd89d0a Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:55:50 +0300 Subject: [PATCH 6/9] Fix tests --- src/ikea_api/wrappers/parsers/order_capture.py | 6 +++--- tests/wrappers/parsers/test_item_pip.py | 9 ++++++--- tests/wrappers/parsers/test_order_capture.py | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ikea_api/wrappers/parsers/order_capture.py b/src/ikea_api/wrappers/parsers/order_capture.py index 1e8b11a..272080f 100644 --- a/src/ikea_api/wrappers/parsers/order_capture.py +++ b/src/ikea_api/wrappers/parsers/order_capture.py @@ -4,8 +4,8 @@ from typing import Any, List, Optional from pydantic import ( # pyright: ignore[reportUnknownVariableType] - AfterValidator, BaseModel, + BeforeValidator, ) from typing_extensions import Annotated @@ -61,7 +61,7 @@ class TimeWindows(BaseModel): class SelectableInfo(BaseModel): - selectable: Annotated[bool, AfterValidator(lambda value: value == "YES")] + selectable: Annotated[bool, BeforeValidator(lambda value: value == "YES")] class Metadata(BaseModel): @@ -245,7 +245,7 @@ def parse_collect_delivery_services( for delivery in service.possibleDeliveries.deliveries: for point in delivery.possiblePickUpPoints.pickUpPoints: date = ( - point.timeWindows.earliestPossibleSlot.fromDateTime + point.timeWindows.earliestPossibleSlot.fromDateTime.date() if point.timeWindows and point.timeWindows.earliestPossibleSlot else None ) diff --git a/tests/wrappers/parsers/test_item_pip.py b/tests/wrappers/parsers/test_item_pip.py index 393b8e8..bd03081 100644 --- a/tests/wrappers/parsers/test_item_pip.py +++ b/tests/wrappers/parsers/test_item_pip.py @@ -3,8 +3,6 @@ from typing import Any import pytest -from pydantic import ValidationError - from ikea_api.wrappers.parsers.pip_item import ( Catalog, CatalogRef, @@ -12,6 +10,8 @@ get_category_name_and_url, parse_pip_item, ) +from pydantic import HttpUrl, ValidationError + from tests.conftest import TestData @@ -21,7 +21,10 @@ def generate_catalog_refs(name: str, url: str): def test_get_category_name_and_url_passes(): name, url = "Книжные шкафы", "https://www.ikea.com/ru/ru/cat/knizhnye-shkafy-10382/" - assert get_category_name_and_url(generate_catalog_refs(name, url)) == (name, url) + assert get_category_name_and_url(generate_catalog_refs(name, url)) == ( + name, + HttpUrl(url), # pyright: ignore[reportCallIssue] + ) def test_get_category_name_and_url_raises(): diff --git a/tests/wrappers/parsers/test_order_capture.py b/tests/wrappers/parsers/test_order_capture.py index c4638f0..8444418 100644 --- a/tests/wrappers/parsers/test_order_capture.py +++ b/tests/wrappers/parsers/test_order_capture.py @@ -54,7 +54,7 @@ def test_get_date_with_value_first(): ) ), ] - assert get_date(deliveries) == exp_datetime + assert get_date(deliveries) == exp_datetime.date() def test_get_date_with_value_not_first(): @@ -67,7 +67,7 @@ def test_get_date_with_value_not_first(): ) ), ] - assert get_date(deliveries) == exp_datetime + assert get_date(deliveries) == exp_datetime.date() def test_get_type_no_service_type(constants: Constants): From 915c45c3ea4be0d62568e3654553b9aa017e414f Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:56:21 +0300 Subject: [PATCH 7/9] Update --- src/ikea_api/wrappers/parsers/order_capture.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ikea_api/wrappers/parsers/order_capture.py b/src/ikea_api/wrappers/parsers/order_capture.py index 272080f..b37ab92 100644 --- a/src/ikea_api/wrappers/parsers/order_capture.py +++ b/src/ikea_api/wrappers/parsers/order_capture.py @@ -3,10 +3,7 @@ from datetime import date, datetime from typing import Any, List, Optional -from pydantic import ( # pyright: ignore[reportUnknownVariableType] - BaseModel, - BeforeValidator, -) +from pydantic import BaseModel, BeforeValidator from typing_extensions import Annotated from ikea_api.constants import Constants From b9ee1812c6abb20409b7deb11bab133456f35038 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:56:55 +0300 Subject: [PATCH 8/9] Fix formatting --- src/ikea_api/abc.py | 15 +++++---------- src/ikea_api/constants.py | 4 +++- tests/wrappers/parsers/test_item_ingka.py | 12 +++++++----- tests/wrappers/parsers/test_item_pip.py | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/ikea_api/abc.py b/src/ikea_api/abc.py index 261e3d1..ec281f5 100644 --- a/src/ikea_api/abc.py +++ b/src/ikea_api/abc.py @@ -45,18 +45,15 @@ class ResponseInfo(ABC): @cached_property @abstractmethod - def text(self) -> str: - ... + def text(self) -> str: ... @cached_property @abstractmethod - def json(self) -> Any: - ... + def json(self) -> Any: ... @property @abstractmethod - def is_success(self) -> bool: - ... + def is_success(self) -> bool: ... EndpointResponse = TypeVar("EndpointResponse") @@ -98,8 +95,7 @@ def wrapper( class SyncExecutor(ABC): @staticmethod @abstractmethod - def request(request: RequestInfo) -> ResponseInfo: - ... + def request(request: RequestInfo) -> ResponseInfo: ... @classmethod def run(cls, endpoint: EndpointInfo[EndpointResponse]) -> EndpointResponse: @@ -121,8 +117,7 @@ def run(cls, endpoint: EndpointInfo[EndpointResponse]) -> EndpointResponse: class AsyncExecutor(ABC): @staticmethod @abstractmethod - async def request(request: RequestInfo) -> ResponseInfo: - ... + async def request(request: RequestInfo) -> ResponseInfo: ... @classmethod async def run(cls, endpoint: EndpointInfo[EndpointResponse]) -> EndpointResponse: diff --git a/src/ikea_api/constants.py b/src/ikea_api/constants.py index 827f4f4..642333a 100644 --- a/src/ikea_api/constants.py +++ b/src/ikea_api/constants.py @@ -6,7 +6,9 @@ @dataclass(frozen=True) class Constants: - user_agent: str = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15" + user_agent: str = ( + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15" + ) base_url: str = "https://www.ikea.com" country: str = "ru" language: str = "ru" diff --git a/tests/wrappers/parsers/test_item_ingka.py b/tests/wrappers/parsers/test_item_ingka.py index 62fbab6..4077006 100644 --- a/tests/wrappers/parsers/test_item_ingka.py +++ b/tests/wrappers/parsers/test_item_ingka.py @@ -95,11 +95,13 @@ def test_get_name( productName=product_name, productType=SimpleNamespace(name=product_type), validDesign=SimpleNamespace(text=design) if design else None, - measurements=SimpleNamespace( - referenceMeasurements=[SimpleNamespace(metric=measurements)] - ) - if measurements - else None, + measurements=( + SimpleNamespace( + referenceMeasurements=[SimpleNamespace(metric=measurements)] + ) + if measurements + else None + ), ) assert get_name(comm) == exp_result diff --git a/tests/wrappers/parsers/test_item_pip.py b/tests/wrappers/parsers/test_item_pip.py index bd03081..ae8d2d8 100644 --- a/tests/wrappers/parsers/test_item_pip.py +++ b/tests/wrappers/parsers/test_item_pip.py @@ -23,7 +23,7 @@ def test_get_category_name_and_url_passes(): name, url = "Книжные шкафы", "https://www.ikea.com/ru/ru/cat/knizhnye-shkafy-10382/" assert get_category_name_and_url(generate_catalog_refs(name, url)) == ( name, - HttpUrl(url), # pyright: ignore[reportCallIssue] + HttpUrl(url), # pyright: ignore[reportCallIssue] ) From a3023c68073b5da32ddd0eff9019ee07b2de5669 Mon Sep 17 00:00:00 2001 From: Lev Vereshchagin Date: Thu, 1 Aug 2024 12:59:25 +0300 Subject: [PATCH 9/9] Fix linting --- src/ikea_api/abc.py | 15 ++++++++++----- src/ikea_api/constants.py | 4 +--- tests/wrappers/parsers/test_item_base.py | 1 + tests/wrappers/parsers/test_item_pip.py | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ikea_api/abc.py b/src/ikea_api/abc.py index ec281f5..261e3d1 100644 --- a/src/ikea_api/abc.py +++ b/src/ikea_api/abc.py @@ -45,15 +45,18 @@ class ResponseInfo(ABC): @cached_property @abstractmethod - def text(self) -> str: ... + def text(self) -> str: + ... @cached_property @abstractmethod - def json(self) -> Any: ... + def json(self) -> Any: + ... @property @abstractmethod - def is_success(self) -> bool: ... + def is_success(self) -> bool: + ... EndpointResponse = TypeVar("EndpointResponse") @@ -95,7 +98,8 @@ def wrapper( class SyncExecutor(ABC): @staticmethod @abstractmethod - def request(request: RequestInfo) -> ResponseInfo: ... + def request(request: RequestInfo) -> ResponseInfo: + ... @classmethod def run(cls, endpoint: EndpointInfo[EndpointResponse]) -> EndpointResponse: @@ -117,7 +121,8 @@ def run(cls, endpoint: EndpointInfo[EndpointResponse]) -> EndpointResponse: class AsyncExecutor(ABC): @staticmethod @abstractmethod - async def request(request: RequestInfo) -> ResponseInfo: ... + async def request(request: RequestInfo) -> ResponseInfo: + ... @classmethod async def run(cls, endpoint: EndpointInfo[EndpointResponse]) -> EndpointResponse: diff --git a/src/ikea_api/constants.py b/src/ikea_api/constants.py index 642333a..827f4f4 100644 --- a/src/ikea_api/constants.py +++ b/src/ikea_api/constants.py @@ -6,9 +6,7 @@ @dataclass(frozen=True) class Constants: - user_agent: str = ( - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15" - ) + user_agent: str = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15" base_url: str = "https://www.ikea.com" country: str = "ru" language: str = "ru" diff --git a/tests/wrappers/parsers/test_item_base.py b/tests/wrappers/parsers/test_item_base.py index 4a3c9a9..8831c6d 100644 --- a/tests/wrappers/parsers/test_item_base.py +++ b/tests/wrappers/parsers/test_item_base.py @@ -1,6 +1,7 @@ from __future__ import annotations import pytest + from ikea_api.wrappers.parsers.item_base import ( ItemType, get_is_combination_from_item_type, diff --git a/tests/wrappers/parsers/test_item_pip.py b/tests/wrappers/parsers/test_item_pip.py index ae8d2d8..45dd71c 100644 --- a/tests/wrappers/parsers/test_item_pip.py +++ b/tests/wrappers/parsers/test_item_pip.py @@ -3,6 +3,8 @@ from typing import Any import pytest +from pydantic import HttpUrl, ValidationError + from ikea_api.wrappers.parsers.pip_item import ( Catalog, CatalogRef, @@ -10,8 +12,6 @@ get_category_name_and_url, parse_pip_item, ) -from pydantic import HttpUrl, ValidationError - from tests.conftest import TestData