Coverage for tests/test_compat.py: 100%

49 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-06 16:22 +0000

1from typing import Any, Dict, List, Union 1abcde

2 

3from fastapi import FastAPI, UploadFile 1abcde

4from fastapi._compat import ( 1abcde

5 ModelField, 

6 Undefined, 

7 _get_model_config, 

8 get_model_fields, 

9 is_bytes_sequence_annotation, 

10 is_scalar_field, 

11 is_uploadfile_sequence_annotation, 

12) 

13from fastapi.testclient import TestClient 1abcde

14from pydantic import BaseConfig, BaseModel, ConfigDict 1abcde

15from pydantic.fields import FieldInfo 1abcde

16 

17from .utils import needs_pydanticv1, needs_pydanticv2 1abcde

18 

19 

20@needs_pydanticv2 1abcde

21def test_model_field_default_required(): 1abcde

22 # For coverage 

23 field_info = FieldInfo(annotation=str) 1zABCD

24 field = ModelField(name="foo", field_info=field_info) 1zABCD

25 assert field.default is Undefined 1zABCD

26 

27 

28@needs_pydanticv1 1abcde

29def test_upload_file_dummy_with_info_plain_validator_function(): 1abcde

30 # For coverage 

31 assert UploadFile.__get_pydantic_core_schema__(str, lambda x: None) == {} 1EFGHI

32 

33 

34@needs_pydanticv1 1abcde

35def test_union_scalar_list(): 1abcde

36 # For coverage 

37 # TODO: there might not be a current valid code path that uses this, it would 

38 # potentially enable query parameters defined as both a scalar and a list 

39 # but that would require more refactors, also not sure it's really useful 

40 from fastapi._compat import is_pv1_scalar_field 1pqrst

41 

42 field_info = FieldInfo() 1pqrst

43 field = ModelField( 1pqrst

44 name="foo", 

45 field_info=field_info, 

46 type_=Union[str, List[int]], 

47 class_validators={}, 

48 model_config=BaseConfig, 

49 ) 

50 assert not is_pv1_scalar_field(field) 1pqrst

51 

52 

53@needs_pydanticv2 1abcde

54def test_get_model_config(): 1abcde

55 # For coverage in Pydantic v2 

56 class Foo(BaseModel): 1klmno

57 model_config = ConfigDict(from_attributes=True) 1klmno

58 

59 foo = Foo() 1klmno

60 config = _get_model_config(foo) 1klmno

61 assert config == {"from_attributes": True} 1klmno

62 

63 

64def test_complex(): 1abcde

65 app = FastAPI() 1fghij

66 

67 @app.post("/") 1fghij

68 def foo(foo: Union[str, List[int]]): 1fghij

69 return foo 1fghij

70 

71 client = TestClient(app) 1fghij

72 

73 response = client.post("/", json="bar") 1fghij

74 assert response.status_code == 200, response.text 1fghij

75 assert response.json() == "bar" 1fghij

76 

77 response2 = client.post("/", json=[1, 2]) 1fghij

78 assert response2.status_code == 200, response2.text 1fghij

79 assert response2.json() == [1, 2] 1fghij

80 

81 

82def test_is_bytes_sequence_annotation_union(): 1abcde

83 # For coverage 

84 # TODO: in theory this would allow declaring types that could be lists of bytes 

85 # to be read from files and other types, but I'm not even sure it's a good idea 

86 # to support it as a first class "feature" 

87 assert is_bytes_sequence_annotation(Union[List[str], List[bytes]]) 1JKLMN

88 

89 

90def test_is_uploadfile_sequence_annotation(): 1abcde

91 # For coverage 

92 # TODO: in theory this would allow declaring types that could be lists of UploadFile 

93 # and other types, but I'm not even sure it's a good idea to support it as a first 

94 # class "feature" 

95 assert is_uploadfile_sequence_annotation(Union[List[str], List[UploadFile]]) 1OPQRS

96 

97 

98def test_is_pv1_scalar_field(): 1abcde

99 # For coverage 

100 class Model(BaseModel): 1uvwxy

101 foo: Union[str, Dict[str, Any]] 1uvwxy

102 

103 fields = get_model_fields(Model) 1uvwxy

104 assert not is_scalar_field(fields[0]) 1uvwxy