class MeetingType: id: Optional[int] = Field(response_only=True) title: str = Field(min_length=1) date_start: str = Field(validator=DateValidator()) date_end: str = Field(validator=DateValidator()) owner: str = Field() room_id: int
class BookWithFile(BookNoContent): file: str = Field(description="Book content as base64 string.", request_only=True) format: str = Field( description="Book format.", request_only=True, choices=Converter.supported_formats, )
class Todo: """Todo object definition for the API. Schema will automatically populate fields implicitly. """ id: Optional[int] = Field(response_only=True) title: Optional[str] order: Optional[int] url: Optional[str] = Field(response_only=True) completed: Optional[bool] = Field(default=False)
class Account: id: Optional[int] = Field(response_only=True) username: str password: str = Field(request_only=True, min_length=6) is_admin: bool = Field( allow_coerce=True, response_name="isAdmin", default=False, ) created_at: datetime = Field( response_only=True, response_name="createdAt", default_factory=safe_date, )
def test_fields_can_fail_to_select_validators(): # Given that I have an instance of a field with a nonstandard annotation and validator options field = Field("example", None, minimum=10) # When I call its select_validator method # Then a RuntimeError should be raised with pytest.raises(RuntimeError): field.select_validator()
def test_fields_are_representable(): # Given that I have an instance of a field field = Field("example", int) # When I call repr on it # Then I should get back its string representation assert repr( field ) == "Field(name='example', annotation=<class 'int'>, description=None, default=Missing, default_factory=None, request_name='example', response_name='example', request_only=False, response_only=False, allow_coerce=False, validator=None, validator_options={})" # noqa
def test_fields_can_fail_to_coerce_values(): # Given that I have a Field that allows coercions field = Field(annotation=int, allow_coerce=True) # When I call its validate method with a value that cannot be coerced with pytest.raises(FieldValidationError) as e_data: field.validate("invalid") assert e_data.value.message == "value could not be coerced to int"
class Todo: id: Optional[int] = Field(response_only=True, default=None) description: str = "no description" status: str = Field(choices=["todo", "done"], default="todo")
field.select_validator() def test_fields_are_representable(): # Given that I have an instance of a field field = Field("example", int) # When I call repr on it # Then I should get back its string representation assert repr( field ) == "Field(name='example', annotation=<class 'int'>, description=None, default=Missing, default_factory=None, request_name='example', response_name='example', request_only=False, response_only=False, allow_coerce=False, validator=None, validator_options={})" # noqa @pytest.mark.parametrize("field,value,expected", [ (Field(annotation=int, allow_coerce=True), "1", 1), (Field(annotation=bool, allow_coerce=True), "1", True), (Field(annotation=str, allow_coerce=True), 1, "1"), ]) def test_fields_can_coerce_values(field, value, expected): assert field.validate(value) == expected def test_fields_can_fail_to_coerce_values(): # Given that I have a Field that allows coercions field = Field(annotation=int, allow_coerce=True) # When I call its validate method with a value that cannot be coerced with pytest.raises(FieldValidationError) as e_data: field.validate("invalid")
def test_list_validator(annotation, options, value, expected): _test_validator(ListValidator, Field(annotation=annotation), options, value, expected)
def test_dict_validator(annotation, options, value, expected): _test_validator(DictValidator, Field(annotation=annotation), options, value, expected)
), ]) def test_list_validator(annotation, options, value, expected): _test_validator(ListValidator, Field(annotation=annotation), options, value, expected) @pytest.mark.parametrize("annotation,options,value,expected", [ (Dict, {}, None, FieldValidationError("value must be a dict")), (Dict[Any, Any], {}, {0: "a", "b": 42, "c": None}, {0: "a", "b": 42, "c": None}), (Dict[str, str], {}, {}, {}), (Dict[str, str], {}, {"a": 1}, ValidationError({"a": "unexpected type int"})), (Dict[str, str], {}, {1: "a"}, ValidationError({1: "unexpected type int"})), (Dict[str, str], {}, {"a": "a"}, {"a": "a"}), ( Dict[str, str], {"fields": {"a": Field(annotation=int)}}, {}, ValidationError({"a": "this field is required"}), ), ( Dict[str, str], {"fields": {"a": Field(annotation=int)}}, {"a": "42"}, ValidationError({"a": "unexpected type str"}), ), ( Dict[str, str], {"fields": {"a": Field(annotation=int)}}, {"a": 42}, {"a": 42}, ), ( Dict[str, str], {"fields": { "a": Field(annotation=int),
class UserSchema: id: int = Field(response_only=True) email_address: Optional[str] display_name: Optional[str] title: Optional[str]
class Account: username: str password: str = Field(request_only=True, min_length=8) is_admin: bool = False
class CommentSchema: content: str user_id: int id: int = Field(response_only=True) date_created: datetime = Field(response_only=True)
class Envelope: username: str message: str recipient: str = Field(request_only=True, default="*")
class WithID: id: Optional[str] = Field(response_only=True)
class BookContent(BookNoContent): pages: List[str] = Field(description="Book content.", response_only=True) page_active: Optional[int] = Field( description="Current active page number.", response_only=True)
(Dict[str, str], {}, { "a": 1 }, ValidationError({"a": "unexpected type int"})), (Dict[str, str], {}, { 1: "a" }, ValidationError({1: "unexpected type int"})), (Dict[str, str], {}, { "a": "a" }, { "a": "a" }), ( Dict[str, str], { "fields": { "a": Field(annotation=int) } }, {}, ValidationError({"a": "this field is required"}), ), ( Dict[str, str], { "fields": { "a": Field(annotation=int) } }, { "a": "42" },
class BookNoContent(WithID): title: str = Field(description="Book title.") author: str = Field(description="Book author.", max_length=100, strip_spaces=True) cover: str = Field(description="Book cover image as base64.")
class Application: id: Optional[int] = Field(response_only=True) name: str rating: int
class OrderCreate: url: str = Field(description="Delivery club link") phone: str = Field(description="Your phone number")
def test_union_validator(annotation, value, expected): _test_validator(UnionValidator, Field(annotation=annotation), {}, value, expected)
class Base: x: int y: str = Field(min_length=8)
class RoomType: id: Optional[int] = Field(response_only=True) name: str = Field(min_length=1, max_length=60)
class Kitten: id: int = Field(response_only=True) name: str
def test_fields_with_optional_unions(annotation, value, expected): field = Field(annotation=annotation) field.select_validator() assert field.validate(value) == expected