Coverage for tests/test_inherited_custom_class.py: 100%

69 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-08 03:53 +0000

1import uuid 1abcde

2 

3import pytest 1abcde

4from fastapi import FastAPI 1abcde

5from fastapi.testclient import TestClient 1abcde

6from pydantic import BaseModel 1abcde

7 

8from .utils import needs_pydanticv1, needs_pydanticv2 1abcde

9 

10 

11class MyUuid: 1abcde

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

13 self.uuid = uuid_string 1abcde

14 

15 def __str__(self): 1abcde

16 return self.uuid 1abcde

17 

18 @property # type: ignore 1abcde

19 def __class__(self): 1abcde

20 return uuid.UUID 1abcde

21 

22 @property 1abcde

23 def __dict__(self): 1abcde

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") 1abcde

27 

28 

29@needs_pydanticv2 1abcde

30def test_pydanticv2(): 1abcde

31 from pydantic import field_serializer 1abcde

32 

33 app = FastAPI() 1abcde

34 

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

36 def return_fast_uuid(): 1abcde

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

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

39 assert type(asyncpg_uuid) != uuid.UUID 1abcde

40 with pytest.raises(TypeError): 1abcde

41 vars(asyncpg_uuid) 1abcde

42 return {"fast_uuid": asyncpg_uuid} 1abcde

43 

44 class SomeCustomClass(BaseModel): 1abcde

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

46 

47 a_uuid: MyUuid 1abcde

48 

49 @field_serializer("a_uuid") 1abcde

50 def serialize_a_uuid(self, v): 1abcde

51 return str(v) 1abcde

52 

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

54 def return_some_user(): 1abcde

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

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

57 

58 client = TestClient(app) 1abcde

59 

60 with client: 1abcde

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

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

63 

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

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

66 } 

67 

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

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

70 } 

71 

72 

73# TODO: remove when deprecating Pydantic v1 

74@needs_pydanticv1 1abcde

75def test_pydanticv1(): 1abcde

76 app = FastAPI() 1abcde

77 

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

79 def return_fast_uuid(): 1abcde

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

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

82 assert type(asyncpg_uuid) != uuid.UUID 1abcde

83 with pytest.raises(TypeError): 1abcde

84 vars(asyncpg_uuid) 1abcde

85 return {"fast_uuid": asyncpg_uuid} 1abcde

86 

87 class SomeCustomClass(BaseModel): 1abcde

88 class Config: 1abcde

89 arbitrary_types_allowed = True 1abcde

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

91 

92 a_uuid: MyUuid 1abcde

93 

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

95 def return_some_user(): 1abcde

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

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

98 

99 client = TestClient(app) 1abcde

100 

101 with client: 1abcde

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

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

104 

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

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

107 } 

108 

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

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

111 }