async def test_marshal_with_honour_field_mask_list(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return [{ 'name': 'John Doe', 'age': 42, 'boolean': True }, { 'name': 'Jane Doe', 'age': 33, 'boolean': False }] data = await client.get_json('/test/', headers={'X-Fields': '{name,age}'}) assert data == [{ 'name': 'John Doe', 'age': 42, }, { 'name': 'Jane Doe', 'age': 33, }]
async def test_marshal_with_expose_mask_header(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) async def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} specs = await client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' in op assert len(op['parameters']) == 1 param = op['parameters'][0] assert param['name'] == 'X-Fields' assert param['type'] == 'string' assert param['format'] == 'mask' assert param['in'] == 'header' assert 'required' not in param assert 'default' not in param
def test_marshal_handle_inheritance(self, app): api = Api(app) person = api.model('Person', { 'name': fields.String, 'age': fields.Integer, }) child = api.inherit('Child', person, { 'extra': fields.String, }) data = {'name': 'John Doe', 'age': 42, 'extra': 'extra'} values = ( ('name', { 'name': 'John Doe' }), ('name,extra', { 'name': 'John Doe', 'extra': 'extra' }), ('extra', { 'extra': 'extra' }), ) for value, expected in values: result = marshal(data, child, mask=value) assert result == expected
async def test_marshal_with_expose_custom_mask_header(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) async def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} app.config['RESTPLUS_MASK_HEADER'] = 'X-Mask' specs = await client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' in op assert len(op['parameters']) == 1 param = op['parameters'][0] assert param['name'] == 'X-Mask'
async def test_marshal_does_not_hit_unrequired_attributes( self, app, client): api = Api(app) model = api.model( 'Person', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) class Person(object): def __init__(self, name, age): self.name = name self.age = age @property def boolean(self): raise Exception() @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return Person('John Doe', 42) data = await client.get_json('/test/', headers={'X-Fields': '{name,age}'}) assert data == {'name': 'John Doe', 'age': 42}
def test_with_readonly(self, app): api = Api(app) nested_fields = api.model('NestedModel', {'name': fields.String}) field = fields.Nested(nested_fields, readonly=True) assert field.__schema__ == { 'readOnly': True, 'allOf': [{ '$ref': '#/definitions/NestedModel' }] }
async def test_marshal_with_handle_polymorph(self, app, client): api = Api(app) parent = api.model('Person', { 'name': fields.String, }) child1 = api.inherit('Child1', parent, { 'extra1': fields.String, }) child2 = api.inherit('Child2', parent, { 'extra2': fields.String, }) class Child1(object): name = 'child1' extra1 = 'extra1' class Child2(object): name = 'child2' extra2 = 'extra2' mapping = {Child1: child1, Child2: child2} thing = api.model('Thing', { 'owner': fields.Polymorph(mapping), }) @api.route('/thing-1/') class Thing1Resource(Resource): @api.marshal_with(thing) async def get(self): return {'owner': Child1()} @api.route('/thing-2/') class Thing2Resource(Resource): @api.marshal_with(thing) async def get(self): return {'owner': Child2()} data = await client.get_json('/thing-1/', headers={'X-Fields': 'owner{name}'}) assert data == {'owner': {'name': 'child1'}} data = await client.get_json('/thing-1/', headers={'X-Fields': 'owner{extra1}'}) assert data == {'owner': {'extra1': 'extra1'}} data = await client.get_json('/thing-2/', headers={'X-Fields': 'owner{name}'}) assert data == {'owner': {'name': 'child2'}}
async def test_no_crossdomain(app, client): class Foo(Resource): async def get(self): return "data" api = Api(app) api.add_resource(Foo, '/test/') res = await client.get('/test/') assert res.status_code == 200 assert 'Access-Control-Allow-Origin' not in res.headers assert 'Access-Control-Allow-Methods' not in res.headers assert 'Access-Control-Max-Age' not in res.headers
async def test_access_control_expose_headers(app, client): class Foo(Resource): @cors.crossdomain(origin='*', expose_headers=['X-My-Header', 'X-Another-Header']) async def get(self): return 'data' api = Api(app) api.add_resource(Foo, '/test/') res = await client.get('/test/') assert res.status_code == 200 assert 'X-MY-HEADER' in res.headers['Access-Control-Expose-Headers'] assert 'X-ANOTHER-HEADER' in res.headers['Access-Control-Expose-Headers'] assert (await res.get_data(False)) == 'data'
async def test_crossdomain(app, client): class Foo(Resource): @cors.crossdomain(origin='*') async def get(self): return 'data' api = Api(app) api.add_resource(Foo, '/test/') res = await client.get('/test/') assert res.status_code == 200 assert res.headers['Access-Control-Allow-Origin'] == '*' assert res.headers['Access-Control-Max-Age'] == '21600' assert 'HEAD' in res.headers['Access-Control-Allow-Methods'] assert 'OPTIONS' in res.headers['Access-Control-Allow-Methods'] assert 'GET' in res.headers['Access-Control-Allow-Methods']
async def test_marshal_with_honour_default_model_mask(self, app, client): api = Api(app) model = api.model('Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }, mask='{name,age}') @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} data = await client.get_json('/test/') assert data == {'name': 'John Doe', 'age': 42}
def test_marshal_honour_field_mask(self, app): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) data = {'name': 'John Doe', 'age': 42, 'boolean': True} result = api.marshal(data, model, mask='{name,age}') assert result == { 'name': 'John Doe', 'age': 42, }
async def test_raise_400_on_invalid_mask(self, app, client): api = Api(app) model = api.model('Test', { 'name': fields.String, 'age': fields.Integer, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) async def get(self): pass response = await client.get('/test/', headers={'X-Fields': 'name{,missing}'}) assert response.status_code == 400 assert response.content_type == 'application/json'
def test_list_fields_with_nested_inherited(self, app): api = Api(app) person = api.model('Person', { 'name': fields.String, 'age': fields.Integer }) child = api.inherit('Child', person, {'attr': fields.String}) family = api.model('Family', {'children': fields.List(fields.Nested(child))}) result = mask.apply(family.resolved, 'children{name,attr}') data = { 'children': [ { 'name': 'John', 'age': 5, 'attr': 'value-john' }, { 'name': 'Jane', 'age': 42, 'attr': 'value-jane' }, ] } expected = { 'children': [ { 'name': 'John', 'attr': 'value-john' }, { 'name': 'Jane', 'attr': 'value-jane' }, ] } assert_data(marshal(data, result), expected) # Should leave th original mask untouched assert_data(marshal(data, family), data)
async def test_marshal_with_skip_missing_fields(self, app, client): api = Api(app) model = api.model('Test', { 'name': fields.String, 'age': fields.Integer, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return { 'name': 'John Doe', 'age': 42, } data = await client.get_json('/test/', headers={'X-Fields': '{name,missing}'}) assert data == {'name': 'John Doe'}
async def test_marshal_with_expose_default_model_mask_header( self, app, client): api = Api(app) model = api.model('Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }, mask='{name,age}') @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) async def get(self): pass specs = await client.get_specs() definition = specs['definitions']['Test'] assert 'x-mask' in definition assert definition['x-mask'] == '{name,age}'
async def test_marshal_with_honour_custom_field_mask(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} app.config['RESTPLUS_MASK_HEADER'] = 'X-Mask' data = await client.get_json('/test/', headers={'X-Mask': '{name,age}'}) assert data == {'name': 'John Doe', 'age': 42}
async def test_marshal_with_disabling_mask_header(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): @api.marshal_with(model) async def get(self): return {'name': 'John Doe', 'age': 42, 'boolean': True} app.config['RESTPLUS_MASK_SWAGGER'] = False specs = await client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' not in op
async def test_is_only_exposed_on_marshal_with(self, app, client): api = Api(app) model = api.model( 'Test', { 'name': fields.String, 'age': fields.Integer, 'boolean': fields.Boolean, }) @api.route('/test/') class TestResource(Resource): async def get(self): return api.marshal( { 'name': 'John Doe', 'age': 42, 'boolean': True }, model) specs = await client.get_specs() op = specs['paths']['/test/']['get'] assert 'parameters' not in op
from quart import Quart from quart_restplus import Api, Resource, fields app = Quart(__name__) api = Api( app, version='1.0', title='TodoMVC API', description='A simple TodoMVC API', ) ns = api.namespace('todos', description='TODO operations') todo = api.model( 'Todo', { 'id': fields.Integer(readonly=True, description='The task unique identifier'), 'task': fields.String(required=True, description='The task details') }) class TodoDAO(object): def __init__(self): self.counter = 0 self.todos = [] def get(self, id): for todo in self.todos: if todo['id'] == id:
from quart_restplus import Api from .cat import api as cat_api from .dog import api as dog_api api = Api( title='Zoo API', version='1.0', description='A simple demo API', ) api.add_namespace(cat_api) api.add_namespace(dog_api)
from quart import Quart, request from quart_restplus import Resource, Api app = Quart(__name__) api = Api(app) todos = {} @api.route('/<string:todo_id>') class TodoSimple(Resource): """ You can try this example as follow: $ curl http://localhost:5000/todo1 -d "data=Remember the milk" -X PUT $ curl http://localhost:5000/todo1 {"todo1": "Remember the milk"} $ curl http://localhost:5000/todo2 -d "data=Change my breakpads" -X PUT $ curl http://localhost:5000/todo2 {"todo2": "Change my breakpads"} Or from python if you have requests : >>> from requests import put, get >>> put('http://localhost:5000/todo1', data={'data': 'Remember the milk'}).json {u'todo1': u'Remember the milk'} >>> get('http://localhost:5000/todo1').json {u'todo1': u'Remember the milk'} >>> put('http://localhost:5000/todo2', data={'data': 'Change my breakpads'}).json {u'todo2': u'Change my breakpads'} >>> get('http://localhost:5000/todo2').json {u'todo2': u'Change my breakpads'}
# needs: pip install python-simplexml from simplexml import dumps from quart import make_response, Quart from quart_restplus import Api, Resource, fields async def output_xml(data, code, headers=None): """Makes a Quart response with a XML encoded body""" resp = await make_response(dumps({'response': data}), code) resp.headers.extend(headers or {}) return resp app = Quart(__name__) api = Api(app, default_mediatype='application/xml') api.representations['application/xml'] = output_xml hello_fields = api.model('Hello', {'entry': fields.String}) @api.route('/<string:entry>') class Hello(Resource): """ # you need requests >>> from requests import get >>> get('http://localhost:5000/me').content # default_mediatype '<?xml version="1.0" ?><response><hello>me</hello></response>' >>> get('http://localhost:5000/me', headers={"accept":"application/json"}).content '{"hello": "me"}' >>> get('http://localhost:5000/me', headers={"accept":"application/xml"}).content '<?xml version="1.0" ?><response><hello>me</hello></response>'
def test_api_shortcut(self, app): api = Api(app) parser = api.parser() assert isinstance(parser, RequestParser)
import pytest from quart_restplus import fields, Api, Resource from quart_restplus.swagger import Swagger api = Api() person = api.model('Person', { 'name': fields.String, 'age': fields.Integer }) family = api.model('Family', { 'name': fields.String, 'father': fields.Nested(person), 'mother': fields.Nested(person), 'children': fields.List(fields.Nested(person)) }) @api.route('/families', endpoint='families') class Families(Resource): @api.marshal_with(family) def get(self): """List all families""" pass @api.marshal_with(family) @api.response(201, 'Family created') def post(self): """Create a new family"""
from quart import Quart, Blueprint from quart_restplus import Api, Resource, fields api_v1 = Blueprint('api', __name__, url_prefix='/api/1') api = Api( api_v1, version='1.0', title='Todo API', description='A simple TODO API', ) ns = api.namespace('todos', description='TODO operations') TODOS = { 'todo1': { 'task': 'build an API' }, 'todo2': { 'task': '?????' }, 'todo3': { 'task': 'profit!' }, } todo = api.model( 'Todo', {'task': fields.String(required=True, description='The task details')}) listed_todo = api.model(
def api(self, app): blueprint = Blueprint('api', __name__) api = Api(blueprint) app.register_blueprint(blueprint) yield api
async def test_marshal_with_honour_complex_field_mask_header( self, app, client): api = Api(app) person = api.model('Person', person_fields) child = api.inherit('Child', person, {'attr': fields.String}) family = api.model( 'Family', { 'father': fields.Nested(person), 'mother': fields.Nested(person), 'children': fields.List(fields.Nested(child)), 'free': fields.List(fields.Raw), }) house = api.model( 'House', {'family': fields.Nested(family, attribute='people')}) @api.route('/test/') class TestResource(Resource): @api.marshal_with(house) def get(self): return { 'people': { 'father': { 'name': 'John', 'age': 42 }, 'mother': { 'name': 'Jane', 'age': 42 }, 'children': [ { 'name': 'Jack', 'age': 5, 'attr': 'value-1' }, { 'name': 'Julie', 'age': 7, 'attr': 'value-2' }, ], 'free': [ { 'key-1': '1-1', 'key-2': '1-2' }, { 'key-1': '2-1', 'key-2': '2-2' }, ] } } data = await client.get_json( '/test/', headers={ 'X-Fields': 'family{father{name},mother{age},children{name,attr},free{key-2}}' }) assert data == { 'family': { 'father': { 'name': 'John' }, 'mother': { 'age': 42 }, 'children': [{ 'name': 'Jack', 'attr': 'value-1' }, { 'name': 'Julie', 'attr': 'value-2' }], 'free': [{ 'key-2': '1-2' }, { 'key-2': '2-2' }] } }