Coverage for tests/serializers/msgspec/test_custom_type.py: 100%

21 statements  

« prev     ^ index     » next       coverage.py v7.17.3, created at 2026-11-13 05:19 +0000

1from typing import Any, TypeVar 1abcdefgh

2 

3import pytest 1abcdefgh

4 

5from fast_depends import Depends, Provider, inject 1abcdefgh

6from fast_depends.exceptions import ValidationError 1abcdefgh

7from fast_depends.msgspec import MsgSpecSerializer 1abcdefgh

8 

9T = TypeVar("T") 1abcdefgh

10 

11 

12class CustomType: 1abcdefgh

13 def __init__(self, value): 1abcdefgh

14 self.value = value 1abcdefgh

15 

16 

17def msgspec_custom_type_decoder(t: type[T], obj: Any) -> T: 1abcdefgh

18 # msgspec only calls `dec_hook` for types it cannot handle itself, so `obj` 

19 # is always the still-undecoded raw value here 

20 return t(obj) 1abcdefgh

21 

22 

23def dep(a: CustomType) -> str: 1abcdefgh

24 return a.value 1abcdefgh

25 

26 

27@inject( 1abcdefgh

28 serializer_cls=MsgSpecSerializer(use_fastdepends_errors=True), 1abcdefgh

29 dependency_provider=Provider(), 1abcdefgh

30) 

31def custom_type_without_decoder(a: CustomType = Depends(dep)): ... 1abcdefgh

32 

33 

34@inject( 1abcdefgh

35 serializer_cls=MsgSpecSerializer( 

36 use_fastdepends_errors=True, 

37 dec_hook=msgspec_custom_type_decoder, 

38 ), 

39 dependency_provider=Provider(), 

40) 

41def custom_type_with_decoder(a: CustomType = Depends(dep)) -> str: 1abcdefgh

42 assert isinstance(a, CustomType) 1abcdefgh

43 return a.value 1abcdefgh

44 

45 

46def test_custom_type_cast(): 1abcdefgh

47 custom_type_with_decoder("123") 1abcdefgh

48 

49 with pytest.raises(ValidationError): 1abcdefgh

50 custom_type_without_decoder("123") 1abcdefgh