Last active
February 5, 2023 15:21
-
-
Save SamWarden/00025424b8025c1b2cddb12b035a6604 to your computer and use it in GitHub Desktop.
Tests for dataclass_factory
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Any, Callable, TypeVar | |
from dataclass_factory import Loader, Mediator, Request | |
from dataclass_factory._internal.provider import LoaderProvider, LoaderRequest | |
from dataclass_factory._internal.provider.request_filtering import ExactOriginRC | |
TModel = TypeVar("TModel") | |
TData = TypeVar("TData") | |
class Converter(LoaderProvider): | |
def __init__(self, from_cls: type[TData], to_cls: type[TModel], loader: Callable[[TData], TModel]): | |
self._from_cls = from_cls | |
self._to_cls = to_cls | |
self._loader = loader | |
self._request_checker = ExactOriginRC(to_cls) | |
def _check_request(self, mediator: Mediator, request: Request) -> None: | |
self._request_checker.check_request(mediator, request) | |
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader: | |
next_loader = mediator.provide_from_next() | |
def model_to_model_loader(data): | |
if not isinstance(data, self._from_cls): | |
_loader = next_loader | |
else: | |
_loader = self._loader | |
return _loader(data) | |
return model_to_model_loader |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dataclasses import dataclass | |
import pytest | |
from dataclass_factory import Retort | |
from dataclass_factory._internal.load_error import TypeLoadError | |
from tests.integration.converter import Converter | |
@dataclass | |
class User: | |
id: int | |
username: str | |
@dataclass | |
class Order: | |
id: int | |
owner_id: int | |
@dataclass | |
class DTO: | |
pass | |
@dataclass | |
class UserDTO(DTO): | |
user_id: str | |
username: str | |
@dataclass | |
class OrderDTO(DTO): | |
order_id: int | |
owner_id: int | |
@dataclass | |
class OrderOwner(User): | |
orders: list[Order] | |
@dataclass | |
class OrderOwnerDTO(UserDTO): | |
orders: list[OrderDTO] | |
DTOs = OrderDTO | UserDTO | OrderOwnerDTO | |
@dataclass | |
class UserModel: | |
user_id: int | |
username: str | |
# Converters | |
def convert_user_entity_to_dto(user: User) -> UserDTO: | |
return UserDTO( | |
user_id=str(user.id), | |
username=user.username, | |
) | |
def convert_order_entity_to_dto(order: Order) -> OrderDTO: | |
return OrderDTO( | |
order_id=order.id, | |
owner_id=order.owner_id, | |
) | |
def convert_order_owner_entity_to_dto(order_owner: OrderOwner) -> OrderOwnerDTO: | |
return OrderOwnerDTO( | |
user_id=str(order_owner.id), | |
username=order_owner.username, | |
orders=[ | |
OrderDTO(order_id=order.id, owner_id=order.owner_id) | |
for order in order_owner.orders | |
], | |
) | |
def convert_user_model_to_dto(user: UserModel) -> UserDTO: | |
return UserDTO( | |
user_id=str(user.user_id), | |
username=user.username, | |
) | |
# Tests | |
def test_convert_entity_to_dto(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
)) | |
assert retort.load(User(1, "Jon"), UserDTO) == UserDTO("1", "Jon") | |
def test_raise_error_on_wrong_entity_conversion(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
)) | |
with pytest.raises(TypeLoadError): | |
retort.load(Order(1, 100), UserDTO) | |
def test_convert_entity_to_unknown_dto(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
Converter(Order, OrderDTO, convert_order_entity_to_dto), | |
)) | |
assert retort.load(User(1, "Jon"), UserDTO) == UserDTO("1", "Jon") | |
assert retort.load(Order(1, 100), OrderDTO) == OrderDTO(1, 100) | |
assert retort.load(User(1, "Jon"), DTOs) == UserDTO("1", "Jon") | |
assert retort.load(Order(1, 100), DTOs) == OrderDTO(1, 100) | |
def test_convert_sequence_entities_to_list_dtos(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
Converter(Order, OrderDTO, convert_order_entity_to_dto), | |
)) | |
assert retort.load([User(1, "Jon"), Order(1, 100)], list[DTOs]) == [UserDTO("1", "Jon"), OrderDTO(1, 100)] | |
assert retort.load((User(1, "Jon"), Order(1, 100)), list[DTOs]) == [UserDTO("1", "Jon"), OrderDTO(1, 100)] | |
@pytest.mark.skip("Convert to tuple of dataclasses not working now") | |
def test_convert_sequence_entities_to_tuple_dtos(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
Converter(Order, OrderDTO, convert_order_entity_to_dto), | |
)) | |
assert retort.load((User(1, "Jon"), Order(1, 100)), tuple[UserDTO, OrderDTO]) == (UserDTO("1", "Jon"), OrderDTO(1, 100)) | |
assert retort.load((User(1, "Jon"), Order(1, 100)), tuple[DTOs, DTOs]) == (UserDTO("1", "Jon"), OrderDTO(1, 100)) | |
assert retort.load((User(1, "Jon"), Order(1, 100)), tuple[DTOs, ...]) == (UserDTO("1", "Jon"), OrderDTO(1, 100)) | |
def test_convert_order_owner_entity_to_dto(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
Converter(Order, OrderDTO, convert_order_entity_to_dto), | |
Converter(OrderOwner, OrderOwnerDTO, convert_order_owner_entity_to_dto), | |
)) | |
assert retort.load( | |
OrderOwner(1, "Jon", [Order(1, 100), Order(2, 200)]), | |
OrderOwnerDTO, | |
) == OrderOwnerDTO("1", "Jon", [OrderDTO(1, 100), OrderDTO(2, 200)]) | |
def test_convert_model_to_dto(): | |
retort = Retort(recipe=( | |
Converter(User, UserDTO, convert_user_entity_to_dto), | |
Converter(UserModel, UserDTO, convert_user_model_to_dto), | |
)) | |
assert retort.load(User(1, "Jon"), UserDTO) == UserDTO("1", "Jon") | |
assert retort.load(UserModel(1, "Jon"), UserDTO) == UserDTO("1", "Jon") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment