Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

post_load decorated functions with same name are not executed #1439

Closed
cimourdain opened this issue Oct 31, 2019 · 2 comments
Closed

post_load decorated functions with same name are not executed #1439

cimourdain opened this issue Oct 31, 2019 · 2 comments

Comments

@cimourdain
Copy link

With schema inheritance or mixins, post_load decorators execution is dependant of their function name.

In the following example:

from marshmallow import Schema, fields, post_load


class Schema1(Schema):
    toto = fields.String()

    @post_load
    def schema1_post_load(self, data, **kwargs):
        print('Schema1 post load: data = %s' % data)
        return data


class Schema2(Schema):
    toto = fields.String()

    @post_load
    def schema2_post_load(self, data, **kwargs):
        print('Schema2 post load: data = %s' % data)
        return data


class MixinSchema(Schema2, Schema1):
    titi = fields.String()

    @post_load
    def mixinshchema_post_load(self, data, **kwargs):
        print('MixinSchema post load: data = %s' % data)
        return data


if __name__ == "__main__":
    payload = {
        'toto': 'gfdgefrh',
        'titi': 'fdghfgjhjh'
    }

    result = MixinSchema().load(payload)

This example produces the following output:

MixinSchema post load: data = {'titi': 'fdghfgjhjh', 'toto': 'gfdgefrh'}
Schema1 post load: data = {'titi': 'fdghfgjhjh', 'toto': 'gfdgefrh'}
Schema2 post load: data = {'titi': 'fdghfgjhjh', 'toto': 'gfdgefrh'}

As per the decorators documentation i understand that the execution order is not guaranteed, so the output is fine by me because all the post_loads are executed.

Then, when i give the MixinSchema post_load function the same name as Schema2:

from marshmallow import Schema, fields, post_load


class Schema1(Schema):
    toto = fields.String()

    @post_load
    def schema1_post_load(self, data, **kwargs):
        print('Schema1 post load: data = %s' % data)
        return data


class Schema2(Schema):
    toto = fields.String()

    @post_load
    def schema2_post_load(self, data, **kwargs):
        print('Schema2 post load: data = %s' % data)
        return data


class MixinSchema(Schema2, Schema1):
    titi = fields.String()

    @post_load
    def schema2_post_load(self, data, **kwargs):
        print('MixinSchema post load: data = %s' % data)
        return data


if __name__ == "__main__":
    payload = {
        'toto': 'gfdgefrh',
        'titi': 'fdghfgjhjh'
    }

    result = MixinSchema().load(payload)

Then i get the following output:

Schema1 post load: data = {'titi': 'fdghfgjhjh', 'toto': 'gfdgefrh'}
MixinSchema post load: data = {'titi': 'fdghfgjhjh', 'toto': 'gfdgefrh'}

The Schema2 post_load is not executed. From my point of view, post_load execution should not be dependant of function naming.

@cimourdain cimourdain changed the title post_load post_load decorated functions with same name are not executed Oct 31, 2019
@lafrech
Copy link
Member

lafrech commented Oct 31, 2019

This is standard Python inheritance. You're overridding the method.

Note that if you didn't decorate the override method in the mixin, it wouldn't even be called.

You could call the overridden method from the mixin using super().

Overall, I think I'm still in favour of replacing the decoration mechanism by hooks. By hooks, I mean the Base schema would have post_load etc. no-op methods that would be called in the process and the user would override those.

The downside is that you'd need to merge methods if you have several post_load processings, but when you do, if you rely on the execution order, you need to merge them anyway, so...

Discussed in #600 (comment).

@cimourdain
Copy link
Author

I agree with you, I too would be in favour of using hook. With schemas with large inheritance/mixin trees it is sometimes hard to find that you override the post_load decorated method (as it is often called def post_load() in all schemas).

I close the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants