1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
import io
from tempfile import SpooledTemporaryFile
import pytest
from flask import url_for
from marshmallow import missing
from marshmallow.exceptions import ValidationError
from werkzeug.datastructures import FileStorage
from werkzeug.routing import BuildError
from flask_marshmallow.fields import _tpl
@pytest.mark.parametrize(
"template", ["<id>", " <id>", "<id> ", "< id>", "<id >", "< id >"]
)
def test_tpl(template):
assert _tpl(template) == "id"
assert _tpl(template) == "id"
assert _tpl(template) == "id"
def test_url_field(ma, mockauthor):
field = ma.URLFor("author", values=dict(id="<id>"))
result = field.serialize("url", mockauthor)
assert result == url_for("author", id=mockauthor.id)
mockauthor.id = 0
result = field.serialize("url", mockauthor)
assert result == url_for("author", id=0)
def test_url_field_with_invalid_attribute(ma, mockauthor):
field = ma.URLFor("author", values=dict(id="<not-an-attr>"))
expected_msg = "{!r} is not a valid attribute of {!r}".format(
"not-an-attr", mockauthor
)
with pytest.raises(AttributeError, match=expected_msg):
field.serialize("url", mockauthor)
def test_url_field_handles_nested_attribute(ma, mockbook, mockauthor):
field = ma.URLFor("author", values=dict(id="<author.id>"))
result = field.serialize("url", mockbook)
assert result == url_for("author", id=mockauthor.id)
def test_url_field_handles_none_attribute(ma, mockbook, mockauthor):
mockbook.author = None
field = ma.URLFor("author", values=dict(id="<author>"))
result = field.serialize("url", mockbook)
assert result is None
field = ma.URLFor("author", values=dict(id="<author.id>"))
result = field.serialize("url", mockbook)
assert result is None
def test_url_field_deserialization(ma):
field = ma.URLFor("author", values=dict(id="<not-an-attr>"), allow_none=True)
# noop
assert field.deserialize("foo") == "foo"
assert field.deserialize(None) is None
def test_invalid_endpoint_raises_build_error(ma, mockauthor):
field = ma.URLFor("badendpoint")
with pytest.raises(BuildError):
field.serialize("url", mockauthor)
def test_hyperlinks_field(ma, mockauthor):
field = ma.Hyperlinks(
{
"self": ma.URLFor("author", values={"id": "<id>"}),
"collection": ma.URLFor("authors"),
}
)
result = field.serialize("_links", mockauthor)
assert result == {
"self": url_for("author", id=mockauthor.id),
"collection": url_for("authors"),
}
def test_hyperlinks_field_recurses(ma, mockauthor):
field = ma.Hyperlinks(
{
"self": {
"href": ma.URLFor("author", values={"id": "<id>"}),
"title": "The author",
},
"collection": {"href": ma.URLFor("authors"), "title": "Authors list"},
}
)
result = field.serialize("_links", mockauthor)
assert result == {
"self": {"href": url_for("author", id=mockauthor.id), "title": "The author"},
"collection": {"href": url_for("authors"), "title": "Authors list"},
}
def test_hyperlinks_field_recurses_into_list(ma, mockauthor):
field = ma.Hyperlinks(
[
{"rel": "self", "href": ma.URLFor("author", values={"id": "<id>"})},
{"rel": "collection", "href": ma.URLFor("authors")},
]
)
result = field.serialize("_links", mockauthor)
assert result == [
{"rel": "self", "href": url_for("author", id=mockauthor.id)},
{"rel": "collection", "href": url_for("authors")},
]
def test_hyperlinks_field_deserialization(ma):
field = ma.Hyperlinks(
{"href": ma.URLFor("author", values={"id": "<id>"})}, allow_none=True
)
# noop
assert field.deserialize("/author") == "/author"
assert field.deserialize(None) is None
def test_absolute_url(ma, mockauthor):
field = ma.AbsoluteURLFor("authors")
result = field.serialize("abs_url", mockauthor)
assert result == url_for("authors", _external=True)
def test_absolute_url_deserialization(ma):
field = ma.AbsoluteURLFor("authors", allow_none=True)
assert field.deserialize("foo") == "foo"
assert field.deserialize(None) is None
def test_aliases(ma):
from flask_marshmallow.fields import AbsoluteURLFor, AbsoluteUrlFor, URLFor, UrlFor
assert UrlFor is URLFor
assert AbsoluteUrlFor is AbsoluteURLFor
def test_file_field(ma, mockauthor):
field = ma.File()
fs = FileStorage(io.BytesIO(b"test"), "test.jpg")
result = field.deserialize(fs, mockauthor)
assert result == fs
with SpooledTemporaryFile() as temp:
temp.write(b"temp")
fs = FileStorage(temp, "temp.jpg")
result = field.deserialize(fs, mockauthor)
assert result == fs
result = field.deserialize("", mockauthor)
assert result is missing
with pytest.raises(ValidationError, match="Field may not be null."):
field.deserialize(None, mockauthor)
with pytest.raises(ValidationError, match="Not a valid file."):
field.deserialize("123", mockauthor)
def test_config_field(ma, app, mockauthor):
app.config["NAME"] = "test"
field = ma.Config(key="NAME")
result = field.serialize("config_value", mockauthor)
assert result == "test"
field = ma.Config(key="DOES_NOT_EXIST")
with pytest.raises(ValueError, match="not found in the app config"):
field.serialize("config_value", mockauthor)
|