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
« prev ^ index » next coverage.py v7.6.1, created at 2025-12-04 08:29 +0000
1import uuid 1nopqrst
3import pytest 1nopqrst
4from fastapi import FastAPI 1nopqrst
5from fastapi.testclient import TestClient 1nopqrst
6from pydantic import BaseModel 1nopqrst
8from .utils import needs_pydanticv1, needs_pydanticv2 1nopqrst
11class MyUuid: 1nopqrst
12 def __init__(self, uuid_string: str): 1nopqrst
13 self.uuid = uuid_string 1haibjckdlemfg
15 def __str__(self): 1nopqrst
16 return self.uuid 1haibjckdlemfg
18 @property # type: ignore 1nopqrst
19 def __class__(self): 1nopqrst
20 return uuid.UUID 1haibjckdlemfg
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
29@needs_pydanticv2 1nopqrst
30def test_pydanticv2(): 1nopqrst
31 from pydantic import field_serializer 1abcdefg
33 app = FastAPI() 1abcdefg
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
44 class SomeCustomClass(BaseModel): 1abcdefg
45 model_config = {"arbitrary_types_allowed": True} 1abcdefg
47 a_uuid: MyUuid 1abcdefg
49 @field_serializer("a_uuid") 1abcdefg
50 def serialize_a_uuid(self, v): 1abcdefg
51 return str(v) 1abcdefg
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
58 client = TestClient(app) 1abcdefg
60 with client: 1abcdefg
61 response_simple = client.get("/fast_uuid") 1abcdefg
62 response_pydantic = client.get("/get_custom_class") 1abcdefg
64 assert response_simple.json() == { 1abcdefg
65 "fast_uuid": "a10ff360-3b1e-4984-a26f-d3ab460bdb51"
66 }
68 assert response_pydantic.json() == { 1abcdefg
69 "a_uuid": "b8799909-f914-42de-91bc-95c819218d01"
70 }
73# TODO: remove when deprecating Pydantic v1
74@needs_pydanticv1 1nopqrst
75def test_pydanticv1(): 1nopqrst
76 app = FastAPI() 1hijklm
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
87 class SomeCustomClass(BaseModel): 1hijklm
88 class Config: 1hijklm
89 arbitrary_types_allowed = True 1hijklm
90 json_encoders = {uuid.UUID: str} 1hijklm
92 a_uuid: MyUuid 1hijklm
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
99 client = TestClient(app) 1hijklm
101 with client: 1hijklm
102 response_simple = client.get("/fast_uuid") 1hijklm
103 response_pydantic = client.get("/get_custom_class") 1hijklm
105 assert response_simple.json() == { 1hijklm
106 "fast_uuid": "a10ff360-3b1e-4984-a26f-d3ab460bdb51"
107 }
109 assert response_pydantic.json() == { 1hijklm
110 "a_uuid": "b8799909-f914-42de-91bc-95c819218d01"
111 }