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'}}
    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
    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_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'
                }]
            }
        }