Coverage for tests/test_inherited_custom_class.py: 100%

69 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-12-04 08:29 +0000

1import uuid 1nopqrst

2 

3import pytest 1nopqrst

4from fastapi import FastAPI 1nopqrst

5from fastapi.testclient import TestClient 1nopqrst

6from pydantic import BaseModel 1nopqrst

7 

8from .utils import needs_pydanticv1, needs_pydanticv2 1nopqrst

9 

10 

11class MyUuid: 1nopqrst

12 def __init__(self, uuid_string: str): 1nopqrst

13 self.uuid = uuid_string 1haibjckdlemfg

14 

15 def __str__(self): 1nopqrst

16 return self.uuid 1haibjckdlemfg

17 

18 @property # type: ignore 1nopqrst

19 def __class__(self): 1nopqrst

20 return uuid.UUID 1haibjckdlemfg

21 

22 @property 1nopqrst

23 def __dict__(self): 1nopqrst

24 """Spoof a missing __dict__ by raising TypeError, this is how 

25 asyncpg.pgroto.pgproto.UUID behaves""" 

26 raise TypeError("vars() argument must have __dict__ attribute") 1haibjckdlemfg

27 

28 

29@needs_pydanticv2 1nopqrst

30def test_pydanticv2(): 1nopqrst

31 from pydantic import field_serializer 1abcdefg

32 

33 app = FastAPI() 1abcdefg

34 

35 @app.get("/fast_uuid") 1abcdefg

36 def return_fast_uuid(): 1abcdefg

37 asyncpg_uuid = MyUuid("a10ff360-3b1e-4984-a26f-d3ab460bdb51") 1abcdefg

38 assert isinstance(asyncpg_uuid, uuid.UUID) 1abcdefg

39 assert type(asyncpg_uuid) is not uuid.UUID 1abcdefg

40 with pytest.raises(TypeError): 1abcdefg

41 vars(asyncpg_uuid) 1abcdefg

42 return {"fast_uuid": asyncpg_uuid} 1abcdefg

43 

44 class SomeCustomClass(BaseModel): 1abcdefg

45 model_config = {"arbitrary_types_allowed": True} 1abcdefg

46 

47 a_uuid: MyUuid 1abcdefg

48 

49 @field_serializer("a_uuid") 1abcdefg

50 def serialize_a_uuid(self, v): 1abcdefg

51 return str(v) 1abcdefg

52 

53 @app.get("/get_custom_class") 1abcdefg

54 def return_some_user(): 1abcdefg

55 # Test that the fix also works for custom pydantic classes 

56 return SomeCustomClass(a_uuid=MyUuid("b8799909-f914-42de-91bc-95c819218d01")) 1abcdefg

57 

58 client = TestClient(app) 1abcdefg

59 

60 with client: 1abcdefg

61 response_simple = client.get("/fast_uuid") 1abcdefg

62 response_pydantic = client.get("/get_custom_class") 1abcdefg

63 

64 assert response_simple.json() == { 1abcdefg

65 "fast_uuid": "a10ff360-3b1e-4984-a26f-d3ab460bdb51" 

66 } 

67 

68 assert response_pydantic.json() == { 1abcdefg

69 "a_uuid": "b8799909-f914-42de-91bc-95c819218d01" 

70 } 

71 

72 

73# TODO: remove when deprecating Pydantic v1 

74@needs_pydanticv1 1nopqrst

75def test_pydanticv1(): 1nopqrst

76 app = FastAPI() 1hijklm

77 

78 @app.get("/fast_uuid") 1hijklm

79 def return_fast_uuid(): 1hijklm

80 asyncpg_uuid = MyUuid("a10ff360-3b1e-4984-a26f-d3ab460bdb51") 1hijklm

81 assert isinstance(asyncpg_uuid, uuid.UUID) 1hijklm

82 assert type(asyncpg_uuid) is not uuid.UUID 1hijklm

83 with pytest.raises(TypeError): 1hijklm

84 vars(asyncpg_uuid) 1hijklm

85 return {"fast_uuid": asyncpg_uuid} 1hijklm

86 

87 class SomeCustomClass(BaseModel): 1hijklm

88 class Config: 1hijklm

89 arbitrary_types_allowed = True 1hijklm

90 json_encoders = {uuid.UUID: str} 1hijklm

91 

92 a_uuid: MyUuid 1hijklm

93 

94 @app.get("/get_custom_class") 1hijklm

95 def return_some_user(): 1hijklm

96 # Test that the fix also works for custom pydantic classes 

97 return SomeCustomClass(a_uuid=MyUuid("b8799909-f914-42de-91bc-95c819218d01")) 1hijklm

98 

99 client = TestClient(app) 1hijklm

100 

101 with client: 1hijklm

102 response_simple = client.get("/fast_uuid") 1hijklm

103 response_pydantic = client.get("/get_custom_class") 1hijklm

104 

105 assert response_simple.json() == { 1hijklm

106 "fast_uuid": "a10ff360-3b1e-4984-a26f-d3ab460bdb51" 

107 } 

108 

109 assert response_pydantic.json() == { 1hijklm

110 "a_uuid": "b8799909-f914-42de-91bc-95c819218d01" 

111 }