oggit/packages/flask-restx/opengnsys-flask-restx-1.3.0/tests/test_reqparse.py

1123 lines
36 KiB
Python

import decimal
import json
import io
import pytest
from werkzeug.exceptions import BadRequest
from werkzeug.wrappers import Request
from werkzeug.datastructures import FileStorage, MultiDict
from flask_restx import Api, Model, fields, inputs
from flask_restx.errors import SpecsError
from flask_restx.reqparse import Argument, RequestParser, ParseResult
class ReqParseTest(object):
def test_api_shortcut(self, app):
api = Api(app)
parser = api.parser()
assert isinstance(parser, RequestParser)
def test_parse_model(self, app):
model = Model("Todo", {"task": fields.String(required=True)})
parser = RequestParser()
parser.add_argument("todo", type=model, required=True)
data = {"todo": {"task": "aaa"}}
with app.test_request_context(
"/", method="post", data=json.dumps(data), content_type="application/json"
):
args = parser.parse_args()
assert args["todo"] == {"task": "aaa"}
def test_help(self, app, mocker):
abort = mocker.patch(
"flask_restx.reqparse.abort", side_effect=BadRequest("Bad Request")
)
parser = RequestParser()
parser.add_argument("foo", choices=("one", "two"), help="Bad choice.")
req = mocker.Mock(["values", "get_json"])
req.values = MultiDict([("foo", "three")])
req.get_json.return_value = None
with pytest.raises(BadRequest):
parser.parse_args(req)
expected = {
"foo": "Bad choice. The value 'three' is not a valid choice for 'foo'."
}
abort.assert_called_with(
400, "Input payload validation failed", errors=expected
)
def test_no_help(self, app, mocker):
abort = mocker.patch(
"flask_restx.reqparse.abort", side_effect=BadRequest("Bad Request")
)
parser = RequestParser()
parser.add_argument("foo", choices=["one", "two"])
req = mocker.Mock(["values", "get_json"])
req.get_json.return_value = None
req.values = MultiDict([("foo", "three")])
with pytest.raises(BadRequest):
parser.parse_args(req)
expected = {"foo": "The value 'three' is not a valid choice for 'foo'."}
abort.assert_called_with(
400, "Input payload validation failed", errors=expected
)
@pytest.mark.request_context()
def test_viewargs(self, mocker):
req = Request.from_values()
req.view_args = {"foo": "bar"}
parser = RequestParser()
parser.add_argument("foo", location=["view_args"])
args = parser.parse_args(req)
assert args["foo"] == "bar"
req = mocker.Mock(["get_json"])
req.values = ()
req.get_json.return_value = None
req.view_args = {"foo": "bar"}
parser = RequestParser()
parser.add_argument("foo", store_missing=True)
args = parser.parse_args(req)
assert args["foo"] is None
def test_parse_unicode(self, app):
req = Request.from_values("/bubble?foo=barß")
parser = RequestParser()
parser.add_argument("foo")
args = parser.parse_args(req)
assert args["foo"] == "barß"
def test_parse_unicode_app(self, app):
parser = RequestParser()
parser.add_argument("foo")
with app.test_request_context("/bubble?foo=barß"):
args = parser.parse_args()
assert args["foo"] == "barß"
@pytest.mark.request_context(
"/bubble", method="post", content_type="application/json"
)
def test_json_location(self):
parser = RequestParser()
parser.add_argument("foo", location="json", store_missing=True)
args = parser.parse_args()
assert args["foo"] is None
@pytest.mark.request_context(
"/bubble",
method="post",
data=json.dumps({"foo": "bar"}),
content_type="application/json",
)
def test_get_json_location(self):
parser = RequestParser()
parser.add_argument("foo", location="json")
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble?foo=bar")
def test_parse_append_ignore(self, app):
parser = RequestParser()
parser.add_argument(
"foo", ignore=True, type=int, action="append", store_missing=True
),
args = parser.parse_args()
assert args["foo"] is None
@pytest.mark.request_context("/bubble?")
def test_parse_append_default(self):
parser = RequestParser()
parser.add_argument("foo", action="append", store_missing=True),
args = parser.parse_args()
assert args["foo"] is None
@pytest.mark.request_context("/bubble?foo=bar&foo=bat")
def test_parse_append(self):
parser = RequestParser()
parser.add_argument("foo", action="append"),
args = parser.parse_args()
assert args["foo"] == ["bar", "bat"]
@pytest.mark.request_context("/bubble?foo=bar")
def test_parse_append_single(self):
parser = RequestParser()
parser.add_argument("foo", action="append"),
args = parser.parse_args()
assert args["foo"] == ["bar"]
@pytest.mark.request_context("/bubble?foo=bar")
def test_split_single(self):
parser = RequestParser()
parser.add_argument("foo", action="split"),
args = parser.parse_args()
assert args["foo"] == ["bar"]
@pytest.mark.request_context("/bubble?foo=bar,bat")
def test_split_multiple(self):
parser = RequestParser()
parser.add_argument("foo", action="split"),
args = parser.parse_args()
assert args["foo"] == ["bar", "bat"]
@pytest.mark.request_context("/bubble?foo=1,2,3")
def test_split_multiple_cast(self):
parser = RequestParser()
parser.add_argument("foo", type=int, action="split")
args = parser.parse_args()
assert args["foo"] == [1, 2, 3]
@pytest.mark.request_context("/bubble?foo=bar")
def test_parse_dest(self):
parser = RequestParser()
parser.add_argument("foo", dest="bat")
args = parser.parse_args()
assert args["bat"] == "bar"
@pytest.mark.request_context("/bubble?foo>=bar&foo<=bat&foo=foo")
def test_parse_gte_lte_eq(self):
parser = RequestParser()
parser.add_argument("foo", operators=[">=", "<=", "="], action="append"),
args = parser.parse_args()
assert args["foo"] == ["bar", "bat", "foo"]
@pytest.mark.request_context("/bubble?foo>=bar")
def test_parse_gte(self):
parser = RequestParser()
parser.add_argument("foo", operators=[">="])
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble?foo=bar")
def test_parse_foo_operators_four_hunderd(self):
parser = RequestParser()
parser.add_argument("foo", type=int),
with pytest.raises(BadRequest):
parser.parse_args()
@pytest.mark.request_context("/bubble")
def test_parse_foo_operators_ignore(self):
parser = RequestParser()
parser.add_argument("foo", ignore=True, store_missing=True)
args = parser.parse_args()
assert args["foo"] is None
@pytest.mark.request_context("/bubble?foo<=bar")
def test_parse_lte_gte_mock(self, mocker):
mock_type = mocker.Mock()
parser = RequestParser()
parser.add_argument("foo", type=mock_type, operators=["<="])
parser.parse_args()
mock_type.assert_called_with("bar", "foo", "<=")
@pytest.mark.request_context("/bubble?foo<=bar")
def test_parse_lte_gte_append(self):
parser = RequestParser()
parser.add_argument("foo", operators=["<=", "="], action="append")
args = parser.parse_args()
assert args["foo"] == ["bar"]
@pytest.mark.request_context("/bubble?foo<=bar")
def test_parse_lte_gte_missing(self):
parser = RequestParser()
parser.add_argument("foo", operators=["<=", "="])
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble?foo=bar&foo=bat")
def test_parse_eq_other(self):
parser = RequestParser()
parser.add_argument("foo"),
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble?foo=bar")
def test_parse_eq(self):
parser = RequestParser()
parser.add_argument("foo"),
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble?foo<=bar")
def test_parse_lte(self):
parser = RequestParser()
parser.add_argument("foo", operators=["<="])
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble")
def test_parse_required(self, app):
parser = RequestParser()
parser.add_argument("foo", required=True, location="values")
expected = {
"foo": "Missing required parameter in the post body or the query string"
}
with pytest.raises(BadRequest) as cm:
parser.parse_args()
assert cm.value.data["message"] == "Input payload validation failed"
assert cm.value.data["errors"] == expected
parser = RequestParser()
parser.add_argument("bar", required=True, location=["values", "cookies"])
expected = {
"bar": (
"Missing required parameter in the post body or the query "
"string or the request's cookies"
)
}
with pytest.raises(BadRequest) as cm:
parser.parse_args()
assert cm.value.data["message"] == "Input payload validation failed"
assert cm.value.data["errors"] == expected
@pytest.mark.request_context("/bubble")
@pytest.mark.options(bundle_errors=True)
def test_parse_error_bundling(self, app):
parser = RequestParser()
parser.add_argument("foo", required=True, location="values")
parser.add_argument("bar", required=True, location=["values", "cookies"])
with pytest.raises(BadRequest) as cm:
parser.parse_args()
assert cm.value.data["message"] == "Input payload validation failed"
assert cm.value.data["errors"] == {
"foo": "Missing required parameter in the post body or the query string",
"bar": (
"Missing required parameter in the post body or the query string "
"or the request's cookies"
),
}
@pytest.mark.request_context("/bubble")
@pytest.mark.options(bundle_errors=False)
def test_parse_error_bundling_w_parser_arg(self, app):
parser = RequestParser(bundle_errors=True)
parser.add_argument("foo", required=True, location="values")
parser.add_argument("bar", required=True, location=["values", "cookies"])
with pytest.raises(BadRequest) as cm:
parser.parse_args()
assert cm.value.data["message"] == "Input payload validation failed"
assert cm.value.data["errors"] == {
"foo": "Missing required parameter in the post body or the query string",
"bar": (
"Missing required parameter in the post body or the query string "
"or the request's cookies"
),
}
@pytest.mark.request_context("/bubble")
def test_parse_default_append(self):
parser = RequestParser()
parser.add_argument("foo", default="bar", action="append", store_missing=True)
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble")
def test_parse_default(self):
parser = RequestParser()
parser.add_argument("foo", default="bar", store_missing=True)
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble")
def test_parse_callable_default(self):
parser = RequestParser()
parser.add_argument("foo", default=lambda: "bar", store_missing=True)
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble?foo=bar")
def test_parse(self):
parser = RequestParser()
parser.add_argument("foo"),
args = parser.parse_args()
assert args["foo"] == "bar"
@pytest.mark.request_context("/bubble")
def test_parse_none(self):
parser = RequestParser()
parser.add_argument("foo")
args = parser.parse_args()
assert args["foo"] is None
def test_parse_store_missing(self, app):
req = Request.from_values("/bubble")
parser = RequestParser()
parser.add_argument("foo", store_missing=False)
args = parser.parse_args(req)
assert "foo" not in args
def test_parse_choices_correct(self, app):
req = Request.from_values("/bubble?foo=bat")
parser = RequestParser()
parser.add_argument("foo", choices=["bat"]),
args = parser.parse_args(req)
assert args["foo"] == "bat"
def test_parse_choices(self, app):
req = Request.from_values("/bubble?foo=bar")
parser = RequestParser()
parser.add_argument("foo", choices=["bat"]),
with pytest.raises(BadRequest):
parser.parse_args(req)
def test_parse_choices_sensitive(self, app):
req = Request.from_values("/bubble?foo=BAT")
parser = RequestParser()
parser.add_argument("foo", choices=["bat"], case_sensitive=True),
with pytest.raises(BadRequest):
parser.parse_args(req)
def test_parse_choices_insensitive(self, app):
req = Request.from_values("/bubble?foo=BAT")
parser = RequestParser()
parser.add_argument("foo", choices=["bat"], case_sensitive=False),
args = parser.parse_args(req)
assert "bat" == args.get("foo")
# both choices and args are case_insensitive
req = Request.from_values("/bubble?foo=bat")
parser = RequestParser()
parser.add_argument("foo", choices=["BAT"], case_sensitive=False),
args = parser.parse_args(req)
assert "bat" == args.get("foo")
def test_parse_ignore(self, app):
req = Request.from_values("/bubble?foo=bar")
parser = RequestParser()
parser.add_argument("foo", type=int, ignore=True, store_missing=True),
args = parser.parse_args(req)
assert args["foo"] is None
def test_chaining(self):
parser = RequestParser()
assert parser is parser.add_argument("foo")
def test_result_existence(self):
result = ParseResult()
result.foo = "bar"
result["bar"] = "baz"
assert result["foo"] == "bar"
assert result.bar == "baz"
def test_result_missing(self):
result = ParseResult()
pytest.raises(AttributeError, lambda: result.spam)
pytest.raises(KeyError, lambda: result["eggs"])
def test_result_configurability(self):
req = Request.from_values()
assert isinstance(RequestParser().parse_args(req), ParseResult)
assert type(RequestParser(result_class=dict).parse_args(req)) is dict
def test_none_argument(self, app):
parser = RequestParser()
parser.add_argument("foo", location="json")
with app.test_request_context(
"/bubble",
method="post",
data=json.dumps({"foo": None}),
content_type="application/json",
):
args = parser.parse_args()
assert args["foo"] is None
def test_type_callable(self, app):
req = Request.from_values("/bubble?foo=1")
parser = RequestParser()
parser.add_argument("foo", type=lambda x: x, required=False),
args = parser.parse_args(req)
assert args["foo"] == "1"
def test_type_callable_none(self, app):
parser = RequestParser()
parser.add_argument("foo", type=lambda x: x, location="json", required=False),
with app.test_request_context(
"/bubble",
method="post",
data=json.dumps({"foo": None}),
content_type="application/json",
):
args = parser.parse_args()
assert args["foo"] is None
def test_type_decimal(self, app):
parser = RequestParser()
parser.add_argument("foo", type=decimal.Decimal, location="json")
with app.test_request_context(
"/bubble",
method="post",
data=json.dumps({"foo": "1.0025"}),
content_type="application/json",
):
args = parser.parse_args()
assert args["foo"] == decimal.Decimal("1.0025")
def test_type_filestorage(self, app):
parser = RequestParser()
parser.add_argument("foo", type=FileStorage, location="files")
fdata = "foo bar baz qux".encode("utf-8")
with app.test_request_context(
"/bubble", method="POST", data={"foo": (io.BytesIO(fdata), "baz.txt")}
):
args = parser.parse_args()
assert args["foo"].name == "foo"
assert args["foo"].filename == "baz.txt"
assert args["foo"].read() == fdata
def test_filestorage_custom_type(self, app):
def _custom_type(f):
return FileStorage(
stream=f.stream,
filename="{0}aaaa".format(f.filename),
name="{0}aaaa".format(f.name),
)
parser = RequestParser()
parser.add_argument("foo", type=_custom_type, location="files")
fdata = "foo bar baz qux".encode("utf-8")
with app.test_request_context(
"/bubble", method="POST", data={"foo": (io.BytesIO(fdata), "baz.txt")}
):
args = parser.parse_args()
assert args["foo"].name == "fooaaaa"
assert args["foo"].filename == "baz.txtaaaa"
assert args["foo"].read() == fdata
def test_passing_arguments_object(self, app):
req = Request.from_values("/bubble?foo=bar")
parser = RequestParser()
parser.add_argument(Argument("foo"))
args = parser.parse_args(req)
assert args["foo"] == "bar"
def test_int_choice_types(self, app):
parser = RequestParser()
parser.add_argument("foo", type=int, choices=[1, 2, 3], location="json")
with app.test_request_context(
"/bubble",
method="post",
data=json.dumps({"foo": 5}),
content_type="application/json",
):
with pytest.raises(BadRequest):
parser.parse_args()
def test_int_range_choice_types(self, app):
parser = RequestParser()
parser.add_argument("foo", type=int, choices=range(100), location="json")
with app.test_request_context(
"/bubble",
method="post",
data=json.dumps({"foo": 101}),
content_type="application/json",
):
with pytest.raises(BadRequest):
parser.parse_args()
def test_request_parser_copy(self, app):
req = Request.from_values("/bubble?foo=101&bar=baz")
parser = RequestParser()
foo_arg = Argument("foo", type=int)
parser.args.append(foo_arg)
parser_copy = parser.copy()
# Deepcopy should create a clone of the argument object instead of
# copying a reference to the new args list
assert foo_arg not in parser_copy.args
# Args added to new parser should not be added to the original
bar_arg = Argument("bar")
parser_copy.args.append(bar_arg)
assert bar_arg not in parser.args
args = parser_copy.parse_args(req)
assert args["foo"] == 101
assert args["bar"] == "baz"
def test_request_parse_copy_including_settings(self):
parser = RequestParser(trim=True, bundle_errors=True)
parser_copy = parser.copy()
assert parser.trim == parser_copy.trim
assert parser.bundle_errors == parser_copy.bundle_errors
def test_request_parser_replace_argument(self, app):
req = Request.from_values("/bubble?foo=baz")
parser = RequestParser()
parser.add_argument("foo", type=int)
parser_copy = parser.copy()
parser_copy.replace_argument("foo")
args = parser_copy.parse_args(req)
assert args["foo"] == "baz"
def test_both_json_and_values_location(self, app):
parser = RequestParser()
parser.add_argument("foo", type=int)
parser.add_argument("baz", type=int)
with app.test_request_context(
"/bubble?foo=1",
method="post",
data=json.dumps({"baz": 2}),
content_type="application/json",
):
args = parser.parse_args()
assert args["foo"] == 1
assert args["baz"] == 2
def test_not_json_location_and_content_type_json(self, app):
parser = RequestParser()
parser.add_argument("foo", location="args")
with app.test_request_context(
"/bubble", method="get", content_type="application/json"
):
parser.parse_args() # Should not raise a 400: BadRequest
def test_request_parser_remove_argument(self):
req = Request.from_values("/bubble?foo=baz")
parser = RequestParser()
parser.add_argument("foo", type=int)
parser_copy = parser.copy()
parser_copy.remove_argument("foo")
args = parser_copy.parse_args(req)
assert args == {}
def test_strict_parsing_off(self):
req = Request.from_values("/bubble?foo=baz")
parser = RequestParser()
args = parser.parse_args(req)
assert args == {}
def test_strict_parsing_on(self):
req = Request.from_values("/bubble?foo=baz")
parser = RequestParser()
with pytest.raises(BadRequest):
parser.parse_args(req, strict=True)
def test_strict_parsing_off_partial_hit(self, app):
req = Request.from_values("/bubble?foo=1&bar=bees&n=22")
parser = RequestParser()
parser.add_argument("foo", type=int)
args = parser.parse_args(req)
assert args["foo"] == 1
def test_strict_parsing_on_partial_hit(self, app):
req = Request.from_values("/bubble?foo=1&bar=bees&n=22")
parser = RequestParser()
parser.add_argument("foo", type=int)
with pytest.raises(BadRequest):
parser.parse_args(req, strict=True)
def test_trim_argument(self, app):
req = Request.from_values("/bubble?foo= 1 &bar=bees&n=22")
parser = RequestParser()
parser.add_argument("foo")
args = parser.parse_args(req)
assert args["foo"] == " 1 "
parser = RequestParser()
parser.add_argument("foo", trim=True)
args = parser.parse_args(req)
assert args["foo"] == "1"
parser = RequestParser()
parser.add_argument("foo", trim=True, type=int)
args = parser.parse_args(req)
assert args["foo"] == 1
def test_trim_request_parser(self, app):
req = Request.from_values("/bubble?foo= 1 &bar=bees&n=22")
parser = RequestParser(trim=False)
parser.add_argument("foo")
args = parser.parse_args(req)
assert args["foo"] == " 1 "
parser = RequestParser(trim=True)
parser.add_argument("foo")
args = parser.parse_args(req)
assert args["foo"] == "1"
parser = RequestParser(trim=True)
parser.add_argument("foo", type=int)
args = parser.parse_args(req)
assert args["foo"] == 1
def test_trim_request_parser_override_by_argument(self):
parser = RequestParser(trim=True)
parser.add_argument("foo", trim=False)
assert parser.args[0].trim is False
def test_trim_request_parser_json(self, app):
parser = RequestParser(trim=True)
parser.add_argument("foo", location="json")
parser.add_argument("int1", location="json", type=int)
parser.add_argument("int2", location="json", type=int)
with app.test_request_context(
"/bubble",
method="post",
data=json.dumps({"foo": " bar ", "int1": 1, "int2": " 2 "}),
content_type="application/json",
):
args = parser.parse_args()
assert args["foo"] == "bar"
assert args["int1"] == 1
assert args["int2"] == 2
class ArgumentTest(object):
def test_name(self):
arg = Argument("foo")
assert arg.name == "foo"
def test_dest(self):
arg = Argument("foo", dest="foobar")
assert arg.dest == "foobar"
def test_location_url(self):
arg = Argument("foo", location="url")
assert arg.location == "url"
def test_location_url_list(self):
arg = Argument("foo", location=["url"])
assert arg.location == ["url"]
def test_location_header(self):
arg = Argument("foo", location="headers")
assert arg.location == "headers"
def test_location_json(self):
arg = Argument("foo", location="json")
assert arg.location == "json"
def test_location_get_json(self):
arg = Argument("foo", location="get_json")
assert arg.location == "get_json"
def test_location_header_list(self):
arg = Argument("foo", location=["headers"])
assert arg.location == ["headers"]
def test_type(self):
arg = Argument("foo", type=int)
assert arg.type == int
def test_default(self):
arg = Argument("foo", default=True)
assert arg.default is True
def test_default_help(self):
arg = Argument("foo")
assert arg.help is None
def test_required(self):
arg = Argument("foo", required=True)
assert arg.required is True
def test_ignore(self):
arg = Argument("foo", ignore=True)
assert arg.ignore is True
def test_operator(self):
arg = Argument("foo", operators=[">=", "<=", "="])
assert arg.operators == [">=", "<=", "="]
def test_action_filter(self):
arg = Argument("foo", action="filter")
assert arg.action == "filter"
def test_action(self):
arg = Argument("foo", action="append")
assert arg.action == "append"
def test_choices(self):
arg = Argument("foo", choices=[1, 2])
assert arg.choices == [1, 2]
def test_default_dest(self):
arg = Argument("foo")
assert arg.dest is None
def test_default_operators(self):
arg = Argument("foo")
assert arg.operators[0] == "="
assert len(arg.operators) == 1
def test_default_type(self):
arg = Argument("foo")
sentinel = 666
assert arg.type(sentinel) == "666"
def test_default_default(self):
arg = Argument("foo")
assert arg.default is None
def test_required_default(self):
arg = Argument("foo")
assert arg.required is False
def test_ignore_default(self):
arg = Argument("foo")
assert arg.ignore is False
def test_action_default(self):
arg = Argument("foo")
assert arg.action == "store"
def test_choices_default(self):
arg = Argument("foo")
assert len(arg.choices) == 0
def test_source(self, mocker):
req = mocker.Mock(["args", "headers", "values"])
req.args = {"foo": "bar"}
req.headers = {"baz": "bat"}
arg = Argument("foo", location=["args"])
assert arg.source(req) == MultiDict(req.args)
arg = Argument("foo", location=["headers"])
assert arg.source(req) == MultiDict(req.headers)
def test_convert_default_type_with_null_input(self):
arg = Argument("foo")
assert arg.convert(None, None) is None
def test_convert_with_null_input_when_not_nullable(self):
arg = Argument("foo", nullable=False)
pytest.raises(ValueError, lambda: arg.convert(None, None))
def test_source_bad_location(self, mocker):
req = mocker.Mock(["values"])
arg = Argument("foo", location=["foo"])
assert len(arg.source(req)) == 0 # yes, basically you don't find it
def test_source_default_location(self, mocker):
req = mocker.Mock(["values", "get_json"])
req.get_json.return_value = None
req._get_child_mock = lambda **kwargs: MultiDict()
arg = Argument("foo")
assert arg.source(req) == req.values
def test_option_case_sensitive(self):
arg = Argument("foo", choices=["bar", "baz"], case_sensitive=True)
assert arg.case_sensitive is True
# Insensitive
arg = Argument("foo", choices=["bar", "baz"], case_sensitive=False)
assert arg.case_sensitive is False
# Default
arg = Argument("foo", choices=["bar", "baz"])
assert arg.case_sensitive is True
class RequestParserSchemaTest(object):
def test_empty_parser(self):
parser = RequestParser()
assert parser.__schema__ == []
def test_primitive_types(self):
parser = RequestParser()
parser.add_argument("int", type=int, help="Some integer")
parser.add_argument("str", type=str, help="Some string")
parser.add_argument("float", type=float, help="Some float")
assert parser.__schema__ == [
{
"description": "Some integer",
"type": "integer",
"name": "int",
"in": "query",
},
{
"description": "Some string",
"type": "string",
"name": "str",
"in": "query",
},
{
"description": "Some float",
"type": "number",
"name": "float",
"in": "query",
},
]
def test_unknown_type(self):
parser = RequestParser()
parser.add_argument("unknown", type=lambda v: v)
assert parser.__schema__ == [
{
"name": "unknown",
"type": "string",
"in": "query",
}
]
def test_required(self):
parser = RequestParser()
parser.add_argument("int", type=int, required=True)
assert parser.__schema__ == [
{
"name": "int",
"type": "integer",
"in": "query",
"required": True,
}
]
def test_default(self):
parser = RequestParser()
parser.add_argument("int", type=int, default=5)
assert parser.__schema__ == [
{
"name": "int",
"type": "integer",
"in": "query",
"default": 5,
}
]
def test_default_as_false(self):
parser = RequestParser()
parser.add_argument("bool", type=inputs.boolean, default=False)
assert parser.__schema__ == [
{
"name": "bool",
"type": "boolean",
"in": "query",
"default": False,
}
]
def test_choices(self):
parser = RequestParser()
parser.add_argument("string", type=str, choices=["a", "b"])
assert parser.__schema__ == [
{
"name": "string",
"type": "string",
"in": "query",
"enum": ["a", "b"],
}
]
def test_location(self):
parser = RequestParser()
parser.add_argument("default", type=int)
parser.add_argument("in_values", type=int, location="values")
parser.add_argument("in_query", type=int, location="args")
parser.add_argument("in_headers", type=int, location="headers")
parser.add_argument("in_cookie", type=int, location="cookie")
assert parser.__schema__ == [
{
"name": "default",
"type": "integer",
"in": "query",
},
{
"name": "in_values",
"type": "integer",
"in": "query",
},
{
"name": "in_query",
"type": "integer",
"in": "query",
},
{
"name": "in_headers",
"type": "integer",
"in": "header",
},
]
def test_location_json(self):
parser = RequestParser()
parser.add_argument("in_json", type=str, location="json")
assert parser.__schema__ == [
{
"name": "in_json",
"type": "string",
"in": "body",
}
]
def test_location_form(self):
parser = RequestParser()
parser.add_argument("in_form", type=int, location="form")
assert parser.__schema__ == [
{
"name": "in_form",
"type": "integer",
"in": "formData",
}
]
def test_location_files(self):
parser = RequestParser()
parser.add_argument("in_files", type=FileStorage, location="files")
assert parser.__schema__ == [
{
"name": "in_files",
"type": "file",
"in": "formData",
}
]
def test_form_and_body_location(self):
parser = RequestParser()
parser.add_argument("default", type=int)
parser.add_argument("in_form", type=int, location="form")
parser.add_argument("in_json", type=str, location="json")
with pytest.raises(SpecsError) as cm:
parser.__schema__
assert cm.value.msg == "Can't use formData and body at the same time"
def test_files_and_body_location(self):
parser = RequestParser()
parser.add_argument("default", type=int)
parser.add_argument("in_files", type=FileStorage, location="files")
parser.add_argument("in_json", type=str, location="json")
with pytest.raises(SpecsError) as cm:
parser.__schema__
assert cm.value.msg == "Can't use formData and body at the same time"
def test_models(self):
todo_fields = Model(
"Todo",
{"task": fields.String(required=True, description="The task details")},
)
parser = RequestParser()
parser.add_argument("todo", type=todo_fields)
assert parser.__schema__ == [
{
"name": "todo",
"type": "Todo",
"in": "body",
}
]
def test_lists(self):
parser = RequestParser()
parser.add_argument("int", type=int, action="append")
assert parser.__schema__ == [
{
"name": "int",
"in": "query",
"type": "array",
"collectionFormat": "multi",
"items": {"type": "integer"},
}
]
def test_split_lists(self):
parser = RequestParser()
parser.add_argument("int", type=int, action="split")
assert parser.__schema__ == [
{
"name": "int",
"in": "query",
"type": "array",
"collectionFormat": "csv",
"items": {"type": "integer"},
}
]
def test_schema_interface(self):
def custom(value):
pass
custom.__schema__ = {
"type": "string",
"format": "custom-format",
}
parser = RequestParser()
parser.add_argument("custom", type=custom)
assert parser.__schema__ == [
{
"name": "custom",
"in": "query",
"type": "string",
"format": "custom-format",
}
]
def test_callable_default(self):
parser = RequestParser()
parser.add_argument("int", type=int, default=lambda: 5)
assert parser.__schema__ == [
{
"name": "int",
"type": "integer",
"in": "query",
"default": 5,
}
]