Coverage for tests/test_inherited_custom_class.py: 100%

69 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-01-13 13:38 +0000

1import uuid 1klmno

2 

3import pytest 1klmno

4from fastapi import FastAPI 1klmno

5from fastapi.testclient import TestClient 1klmno

6from pydantic import BaseModel 1klmno

7 

8from .utils import needs_pydanticv1, needs_pydanticv2 1klmno

9 

10 

11class MyUuid: 1klmno

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

13 self.uuid = uuid_string 1fagbhcidje

14 

15 def __str__(self): 1klmno

16 return self.uuid 1fagbhcidje

17 

18 @property # type: ignore 1klmno

19 def __class__(self): 1klmno

20 return uuid.UUID 1fagbhcidje

21 

22 @property 1klmno

23 def __dict__(self): 1klmno

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

27 

28 

29@needs_pydanticv2 1klmno

30def test_pydanticv2(): 1klmno

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) is not 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 1klmno

75def test_pydanticv1(): 1klmno

76 app = FastAPI() 1fghij

77 

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

79 def return_fast_uuid(): 1fghij

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

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

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

83 with pytest.raises(TypeError): 1fghij

84 vars(asyncpg_uuid) 1fghij

85 return {"fast_uuid": asyncpg_uuid} 1fghij

86 

87 class SomeCustomClass(BaseModel): 1fghij

88 class Config: 1fghij

89 arbitrary_types_allowed = True 1fghij

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

91 

92 a_uuid: MyUuid 1fghij

93 

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

95 def return_some_user(): 1fghij

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

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

98 

99 client = TestClient(app) 1fghij

100 

101 with client: 1fghij

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

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

104 

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

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

107 } 

108 

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

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

111 }