Coverage for tests/test_compat.py: 100%
60 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-01-13 13:38 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-01-13 13:38 +0000
1from typing import Any, Dict, List, Union 1abcde
3from fastapi import FastAPI, UploadFile 1abcde
4from fastapi._compat import ( 1abcde
5 ModelField,
6 Undefined,
7 _get_model_config,
8 get_cached_model_fields,
9 get_model_fields,
10 is_bytes_sequence_annotation,
11 is_scalar_field,
12 is_uploadfile_sequence_annotation,
13)
14from fastapi.testclient import TestClient 1abcde
15from pydantic import BaseConfig, BaseModel, ConfigDict 1abcde
16from pydantic.fields import FieldInfo 1abcde
18from .utils import needs_pydanticv1, needs_pydanticv2 1abcde
21@needs_pydanticv2 1abcde
22def test_model_field_default_required(): 1abcde
23 # For coverage
24 field_info = FieldInfo(annotation=str) 1EFGHI
25 field = ModelField(name="foo", field_info=field_info) 1EFGHI
26 assert field.default is Undefined 1EFGHI
29@needs_pydanticv1 1abcde
30def test_upload_file_dummy_with_info_plain_validator_function(): 1abcde
31 # For coverage
32 assert UploadFile.__get_pydantic_core_schema__(str, lambda x: None) == {} 1JKLMN
35@needs_pydanticv1 1abcde
36def test_union_scalar_list(): 1abcde
37 # For coverage
38 # TODO: there might not be a current valid code path that uses this, it would
39 # potentially enable query parameters defined as both a scalar and a list
40 # but that would require more refactors, also not sure it's really useful
41 from fastapi._compat import is_pv1_scalar_field 1uvwxy
43 field_info = FieldInfo() 1uvwxy
44 field = ModelField( 1uvwxy
45 name="foo",
46 field_info=field_info,
47 type_=Union[str, List[int]],
48 class_validators={},
49 model_config=BaseConfig,
50 )
51 assert not is_pv1_scalar_field(field) 1uvwxy
54@needs_pydanticv2 1abcde
55def test_get_model_config(): 1abcde
56 # For coverage in Pydantic v2
57 class Foo(BaseModel): 1pqrst
58 model_config = ConfigDict(from_attributes=True) 1pqrst
60 foo = Foo() 1pqrst
61 config = _get_model_config(foo) 1pqrst
62 assert config == {"from_attributes": True} 1pqrst
65def test_complex(): 1abcde
66 app = FastAPI() 1fghij
68 @app.post("/") 1fghij
69 def foo(foo: Union[str, List[int]]): 1fghij
70 return foo 1fghij
72 client = TestClient(app) 1fghij
74 response = client.post("/", json="bar") 1fghij
75 assert response.status_code == 200, response.text 1fghij
76 assert response.json() == "bar" 1fghij
78 response2 = client.post("/", json=[1, 2]) 1fghij
79 assert response2.status_code == 200, response2.text 1fghij
80 assert response2.json() == [1, 2] 1fghij
83def test_is_bytes_sequence_annotation_union(): 1abcde
84 # For coverage
85 # TODO: in theory this would allow declaring types that could be lists of bytes
86 # to be read from files and other types, but I'm not even sure it's a good idea
87 # to support it as a first class "feature"
88 assert is_bytes_sequence_annotation(Union[List[str], List[bytes]]) 1OPQRS
91def test_is_uploadfile_sequence_annotation(): 1abcde
92 # For coverage
93 # TODO: in theory this would allow declaring types that could be lists of UploadFile
94 # and other types, but I'm not even sure it's a good idea to support it as a first
95 # class "feature"
96 assert is_uploadfile_sequence_annotation(Union[List[str], List[UploadFile]]) 1TUVWX
99def test_is_pv1_scalar_field(): 1abcde
100 # For coverage
101 class Model(BaseModel): 1zABCD
102 foo: Union[str, Dict[str, Any]] 1zABCD
104 fields = get_model_fields(Model) 1zABCD
105 assert not is_scalar_field(fields[0]) 1zABCD
108def test_get_model_fields_cached(): 1abcde
109 class Model(BaseModel): 1klmno
110 foo: str 1klmno
112 non_cached_fields = get_model_fields(Model) 1klmno
113 non_cached_fields2 = get_model_fields(Model) 1klmno
114 cached_fields = get_cached_model_fields(Model) 1klmno
115 cached_fields2 = get_cached_model_fields(Model) 1klmno
116 for f1, f2 in zip(cached_fields, cached_fields2): 1klmno
117 assert f1 is f2 1klmno
119 assert non_cached_fields is not non_cached_fields2 1klmno
120 assert cached_fields is cached_fields2 1klmno