538 lines
18 KiB
Python
538 lines
18 KiB
Python
import pytest
|
|
|
|
from flask_restx import marshal, marshal_with, marshal_with_field, fields, Api, Resource
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
|
# Add a dummy Resource to verify that the app is properly set.
|
|
class HelloWorld(Resource):
|
|
def get(self):
|
|
return {}
|
|
|
|
|
|
class MarshallingTest(object):
|
|
def test_marshal(self):
|
|
model = OrderedDict([("foo", fields.Raw)])
|
|
marshal_dict = OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
output = marshal(marshal_dict, model)
|
|
assert isinstance(output, dict)
|
|
assert not isinstance(output, OrderedDict)
|
|
assert output == {"foo": "bar"}
|
|
|
|
def test_marshal_wildcard_nested(self):
|
|
nest = fields.Nested(
|
|
OrderedDict([("thumbnail", fields.String), ("video", fields.String)])
|
|
)
|
|
wild = fields.Wildcard(nest)
|
|
wildcard_fields = OrderedDict([("*", wild)])
|
|
model = OrderedDict([("preview", fields.Nested(wildcard_fields))])
|
|
sub_dict = OrderedDict(
|
|
[
|
|
("9:16", {"thumbnail": 24, "video": 12}),
|
|
("16:9", {"thumbnail": 25, "video": 11}),
|
|
("1:1", {"thumbnail": 26, "video": 10}),
|
|
]
|
|
)
|
|
marshal_dict = OrderedDict([("preview", sub_dict)])
|
|
output = marshal(marshal_dict, model)
|
|
assert output == {
|
|
"preview": {
|
|
"1:1": {"thumbnail": "26", "video": "10"},
|
|
"16:9": {"thumbnail": "25", "video": "11"},
|
|
"9:16": {"thumbnail": "24", "video": "12"},
|
|
}
|
|
}
|
|
|
|
def test_marshal_wildcard_list(self):
|
|
wild = fields.Wildcard(fields.List(fields.String))
|
|
wildcard_fields = OrderedDict([("*", wild)])
|
|
model = OrderedDict([("preview", fields.Nested(wildcard_fields))])
|
|
sub_dict = OrderedDict(
|
|
[("1:1", [1, 2, 3]), ("16:9", [4, 5, 6]), ("9:16", [7, 8, 9])]
|
|
)
|
|
marshal_dict = OrderedDict([("preview", sub_dict)])
|
|
output = marshal(marshal_dict, model)
|
|
assert output == {
|
|
"preview": {
|
|
"9:16": ["7", "8", "9"],
|
|
"16:9": ["4", "5", "6"],
|
|
"1:1": ["1", "2", "3"],
|
|
}
|
|
}
|
|
|
|
def test_marshal_with_envelope(self):
|
|
model = OrderedDict([("foo", fields.Raw)])
|
|
marshal_dict = OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
output = marshal(marshal_dict, model, envelope="hey")
|
|
assert output == {"hey": {"foo": "bar"}}
|
|
|
|
def test_marshal_wildcard_with_envelope(self):
|
|
wild = fields.Wildcard(fields.String)
|
|
model = OrderedDict([("foo", fields.Raw), ("*", wild)])
|
|
marshal_dict = OrderedDict(
|
|
[("foo", {"bat": "baz"}), ("a", "toto"), ("b", "tata")]
|
|
)
|
|
output = marshal(marshal_dict, model, envelope="hey")
|
|
assert output == {"hey": {"a": "toto", "b": "tata", "foo": {"bat": "baz"}}}
|
|
|
|
def test_marshal_with_skip_none(self):
|
|
model = OrderedDict(
|
|
[("foo", fields.Raw), ("bat", fields.Raw), ("qux", fields.Raw)]
|
|
)
|
|
marshal_dict = OrderedDict([("foo", "bar"), ("bat", None)])
|
|
output = marshal(marshal_dict, model, skip_none=True)
|
|
assert output == {"foo": "bar"}
|
|
|
|
def test_marshal_wildcard_with_skip_none(self):
|
|
wild = fields.Wildcard(fields.String)
|
|
model = OrderedDict([("foo", fields.Raw), ("*", wild)])
|
|
marshal_dict = OrderedDict(
|
|
[("foo", None), ("bat", None), ("baz", "biz"), ("bar", None)]
|
|
)
|
|
output = marshal(marshal_dict, model, skip_none=True)
|
|
assert output == {"baz": "biz"}
|
|
|
|
def test_marshal_decorator(self):
|
|
model = OrderedDict([("foo", fields.Raw)])
|
|
|
|
@marshal_with(model)
|
|
def try_me():
|
|
return OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
|
|
assert try_me() == {"foo": "bar"}
|
|
|
|
def test_marshal_decorator_with_envelope(self):
|
|
model = OrderedDict([("foo", fields.Raw)])
|
|
|
|
@marshal_with(model, envelope="hey")
|
|
def try_me():
|
|
return OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
|
|
assert try_me() == {"hey": {"foo": "bar"}}
|
|
|
|
def test_marshal_decorator_with_skip_none(self):
|
|
model = OrderedDict(
|
|
[("foo", fields.Raw), ("bat", fields.Raw), ("qux", fields.Raw)]
|
|
)
|
|
|
|
@marshal_with(model, skip_none=True)
|
|
def try_me():
|
|
return OrderedDict([("foo", "bar"), ("bat", None)])
|
|
|
|
assert try_me() == {"foo": "bar"}
|
|
|
|
def test_marshal_decorator_tuple(self):
|
|
model = OrderedDict([("foo", fields.Raw)])
|
|
|
|
@marshal_with(model)
|
|
def try_me():
|
|
headers = {"X-test": 123}
|
|
return OrderedDict([("foo", "bar"), ("bat", "baz")]), 200, headers
|
|
|
|
assert try_me() == ({"foo": "bar"}, 200, {"X-test": 123})
|
|
|
|
def test_marshal_decorator_tuple_with_envelope(self):
|
|
model = OrderedDict([("foo", fields.Raw)])
|
|
|
|
@marshal_with(model, envelope="hey")
|
|
def try_me():
|
|
headers = {"X-test": 123}
|
|
return OrderedDict([("foo", "bar"), ("bat", "baz")]), 200, headers
|
|
|
|
assert try_me() == ({"hey": {"foo": "bar"}}, 200, {"X-test": 123})
|
|
|
|
def test_marshal_decorator_tuple_with_skip_none(self):
|
|
model = OrderedDict(
|
|
[("foo", fields.Raw), ("bat", fields.Raw), ("qux", fields.Raw)]
|
|
)
|
|
|
|
@marshal_with(model, skip_none=True)
|
|
def try_me():
|
|
headers = {"X-test": 123}
|
|
return OrderedDict([("foo", "bar"), ("bat", None)]), 200, headers
|
|
|
|
assert try_me() == ({"foo": "bar"}, 200, {"X-test": 123})
|
|
|
|
def test_marshal_field_decorator(self):
|
|
model = fields.Raw
|
|
|
|
@marshal_with_field(model)
|
|
def try_me():
|
|
return "foo"
|
|
|
|
assert try_me() == "foo"
|
|
|
|
def test_marshal_field_decorator_tuple(self):
|
|
model = fields.Raw
|
|
|
|
@marshal_with_field(model)
|
|
def try_me():
|
|
return "foo", 200, {"X-test": 123}
|
|
|
|
assert try_me() == ("foo", 200, {"X-test": 123})
|
|
|
|
def test_marshal_field(self):
|
|
model = OrderedDict({"foo": fields.Raw()})
|
|
marshal_fields = OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
output = marshal(marshal_fields, model)
|
|
assert output == {"foo": "bar"}
|
|
|
|
def test_marshal_tuple(self):
|
|
model = OrderedDict({"foo": fields.Raw})
|
|
marshal_fields = OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
output = marshal((marshal_fields,), model)
|
|
assert output == [{"foo": "bar"}]
|
|
|
|
def test_marshal_tuple_with_envelope(self):
|
|
model = OrderedDict({"foo": fields.Raw})
|
|
marshal_fields = OrderedDict([("foo", "bar"), ("bat", "baz")])
|
|
output = marshal((marshal_fields,), model, envelope="hey")
|
|
assert output == {"hey": [{"foo": "bar"}]}
|
|
|
|
def test_marshal_tuple_with_skip_none(self):
|
|
model = OrderedDict(
|
|
[("foo", fields.Raw), ("bat", fields.Raw), ("qux", fields.Raw)]
|
|
)
|
|
marshal_fields = OrderedDict([("foo", "bar"), ("bat", None)])
|
|
output = marshal((marshal_fields,), model, skip_none=True)
|
|
assert output == [{"foo": "bar"}]
|
|
|
|
def test_marshal_nested(self):
|
|
model = {
|
|
"foo": fields.Raw,
|
|
"fee": fields.Nested({"fye": fields.String}),
|
|
}
|
|
|
|
marshal_fields = {
|
|
"foo": "bar",
|
|
"bat": "baz",
|
|
"fee": {"fye": "fum"},
|
|
}
|
|
expected = {
|
|
"foo": "bar",
|
|
"fee": {"fye": "fum"},
|
|
}
|
|
|
|
output = marshal(marshal_fields, model)
|
|
|
|
assert output == expected
|
|
|
|
def test_marshal_ordered(self):
|
|
model = OrderedDict(
|
|
[("foo", fields.Raw), ("baz", fields.Raw), ("bar", fields.Raw)]
|
|
)
|
|
marshal_fields = {"foo": 1, "baz": 2, "bar": 3}
|
|
expected_ordered = OrderedDict([("foo", 1), ("baz", 2), ("bar", 3)])
|
|
ordered_output = marshal(marshal_fields, model, ordered=True)
|
|
assert ordered_output == expected_ordered
|
|
unordered_output = marshal(marshal_fields, model)
|
|
assert not isinstance(unordered_output, OrderedDict)
|
|
|
|
def test_marshal_nested_ordered(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
{
|
|
"fye": fields.String,
|
|
}
|
|
),
|
|
),
|
|
]
|
|
)
|
|
|
|
marshal_fields = {
|
|
"foo": "bar",
|
|
"bat": "baz",
|
|
"fee": {"fye": "fum"},
|
|
}
|
|
expected = OrderedDict([("foo", "bar"), ("fee", OrderedDict([("fye", "fum")]))])
|
|
|
|
output = marshal(marshal_fields, model, ordered=True)
|
|
|
|
assert isinstance(output, OrderedDict)
|
|
assert output == expected
|
|
assert isinstance(output["fee"], OrderedDict)
|
|
|
|
def test_marshal_nested_with_non_null(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict([("fye", fields.String), ("blah", fields.String)]),
|
|
allow_null=False,
|
|
),
|
|
),
|
|
]
|
|
)
|
|
marshal_fields = [OrderedDict([("foo", "bar"), ("bat", "baz"), ("fee", None)])]
|
|
output = marshal(marshal_fields, model)
|
|
expected = [
|
|
OrderedDict(
|
|
[("foo", "bar"), ("fee", OrderedDict([("fye", None), ("blah", None)]))]
|
|
)
|
|
]
|
|
assert output == expected
|
|
|
|
def test_marshal_nested_with_null(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict([("fye", fields.String), ("blah", fields.String)]),
|
|
allow_null=True,
|
|
),
|
|
),
|
|
]
|
|
)
|
|
marshal_fields = OrderedDict([("foo", "bar"), ("bat", "baz"), ("fee", None)])
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict([("foo", "bar"), ("fee", None)])
|
|
assert output == expected
|
|
|
|
def test_marshal_nested_with_skip_none(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict([("fye", fields.String)]), skip_none=True
|
|
),
|
|
),
|
|
]
|
|
)
|
|
marshal_fields = OrderedDict([("foo", "bar"), ("bat", "baz"), ("fee", None)])
|
|
output = marshal(marshal_fields, model, skip_none=True)
|
|
expected = OrderedDict([("foo", "bar")])
|
|
assert output == expected
|
|
|
|
def test_allow_null_presents_data(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict([("fye", fields.String), ("blah", fields.String)]),
|
|
allow_null=True,
|
|
),
|
|
),
|
|
]
|
|
)
|
|
marshal_fields = OrderedDict(
|
|
[("foo", "bar"), ("bat", "baz"), ("fee", {"blah": "cool"})]
|
|
)
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict(
|
|
[("foo", "bar"), ("fee", OrderedDict([("fye", None), ("blah", "cool")]))]
|
|
)
|
|
assert output == expected
|
|
|
|
def test_skip_none_presents_data(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict(
|
|
[
|
|
("fye", fields.String),
|
|
("blah", fields.String),
|
|
("foe", fields.String),
|
|
]
|
|
),
|
|
skip_none=True,
|
|
),
|
|
),
|
|
]
|
|
)
|
|
marshal_fields = OrderedDict(
|
|
[("foo", "bar"), ("bat", "baz"), ("fee", {"blah": "cool", "foe": None})]
|
|
)
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict(
|
|
[("foo", "bar"), ("fee", OrderedDict([("blah", "cool")]))]
|
|
)
|
|
assert output == expected
|
|
|
|
def test_marshal_nested_property(self):
|
|
class TestObject(object):
|
|
@property
|
|
def fee(self):
|
|
return {"blah": "cool"}
|
|
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict([("fye", fields.String), ("blah", fields.String)]),
|
|
allow_null=True,
|
|
),
|
|
),
|
|
]
|
|
)
|
|
obj = TestObject()
|
|
obj.foo = "bar"
|
|
obj.bat = "baz"
|
|
output = marshal([obj], model)
|
|
expected = [
|
|
OrderedDict(
|
|
[
|
|
("foo", "bar"),
|
|
("fee", OrderedDict([("fye", None), ("blah", "cool")])),
|
|
]
|
|
)
|
|
]
|
|
assert output == expected
|
|
|
|
def test_marshal_nested_property_with_skip_none(self):
|
|
class TestObject(object):
|
|
@property
|
|
def fee(self):
|
|
return {"blah": "cool", "foe": None}
|
|
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"fee",
|
|
fields.Nested(
|
|
OrderedDict(
|
|
[
|
|
("fye", fields.String),
|
|
("blah", fields.String),
|
|
("foe", fields.String),
|
|
]
|
|
),
|
|
skip_none=True,
|
|
),
|
|
),
|
|
]
|
|
)
|
|
obj = TestObject()
|
|
obj.foo = "bar"
|
|
obj.bat = "baz"
|
|
output = marshal([obj], model)
|
|
expected = [
|
|
OrderedDict([("foo", "bar"), ("fee", OrderedDict([("blah", "cool")]))])
|
|
]
|
|
assert output == expected
|
|
|
|
def test_marshal_list(self):
|
|
model = OrderedDict([("foo", fields.Raw), ("fee", fields.List(fields.String))])
|
|
marshal_fields = OrderedDict(
|
|
[("foo", "bar"), ("bat", "baz"), ("fee", ["fye", "fum"])]
|
|
)
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict([("foo", "bar"), ("fee", (["fye", "fum"]))])
|
|
assert output == expected
|
|
|
|
def test_marshal_list_of_nesteds(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
("fee", fields.List(fields.Nested({"fye": fields.String}))),
|
|
]
|
|
)
|
|
marshal_fields = OrderedDict(
|
|
[("foo", "bar"), ("bat", "baz"), ("fee", {"fye": "fum"})]
|
|
)
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict(
|
|
[("foo", "bar"), ("fee", [OrderedDict([("fye", "fum")])])]
|
|
)
|
|
assert output == expected
|
|
|
|
def test_marshal_list_of_lists(self):
|
|
model = OrderedDict(
|
|
[("foo", fields.Raw), ("fee", fields.List(fields.List(fields.String)))]
|
|
)
|
|
marshal_fields = OrderedDict(
|
|
[("foo", "bar"), ("bat", "baz"), ("fee", [["fye"], ["fum"]])]
|
|
)
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict([("foo", "bar"), ("fee", [["fye"], ["fum"]])])
|
|
assert output == expected
|
|
|
|
def test_marshal_nested_dict(self):
|
|
model = OrderedDict(
|
|
[
|
|
("foo", fields.Raw),
|
|
(
|
|
"bar",
|
|
OrderedDict(
|
|
[
|
|
("a", fields.Raw),
|
|
("b", fields.Raw),
|
|
]
|
|
),
|
|
),
|
|
]
|
|
)
|
|
marshal_fields = OrderedDict(
|
|
[
|
|
("foo", "foo-val"),
|
|
("bar", "bar-val"),
|
|
("bat", "bat-val"),
|
|
("a", 1),
|
|
("b", 2),
|
|
("c", 3),
|
|
]
|
|
)
|
|
output = marshal(marshal_fields, model)
|
|
expected = OrderedDict(
|
|
[("foo", "foo-val"), ("bar", OrderedDict([("a", 1), ("b", 2)]))]
|
|
)
|
|
assert output == expected
|
|
|
|
@pytest.mark.options(debug=True)
|
|
def test_will_prettyprint_json_in_debug_mode(self, app, client):
|
|
api = Api(app)
|
|
|
|
class Foo1(Resource):
|
|
def get(self):
|
|
return {"foo": "bar", "baz": "asdf"}
|
|
|
|
api.add_resource(Foo1, "/foo", endpoint="bar")
|
|
|
|
foo = client.get("/foo")
|
|
|
|
# Python's dictionaries have random order (as of "new" Pythons,
|
|
# anyway), so we can't verify the actual output here. We just
|
|
# assert that they're properly prettyprinted.
|
|
lines = foo.data.splitlines()
|
|
lines = [line.decode() for line in lines]
|
|
assert "{" == lines[0]
|
|
assert lines[1].startswith(" ")
|
|
assert lines[2].startswith(" ")
|
|
assert "}" == lines[3]
|
|
|
|
# Assert our trailing newline.
|
|
assert foo.data.endswith(b"\n")
|
|
|
|
def test_json_float_marshalled(self, app, client):
|
|
api = Api(app)
|
|
|
|
class FooResource(Resource):
|
|
fields = {"foo": fields.Float}
|
|
|
|
def get(self):
|
|
return marshal({"foo": 3.0}, self.fields)
|
|
|
|
api.add_resource(FooResource, "/api")
|
|
|
|
resp = client.get("/api")
|
|
assert resp.status_code == 200
|
|
assert resp.data.decode("utf-8") == '{"foo": 3.0}\n'
|