From 7062102aa9984a4139c6e08a6544c34f7322952a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fern=C3=A1ndez=20Ramos?= Date: Mon, 24 Sep 2018 18:32:55 +0200 Subject: [PATCH 1/2] Fixes #103, adds support for `@post_load`: Marshmallow `@post_load` decorator can be used as a factory object, to directly return an instance instead of the usual dictionary. This commit adds support for it. --- flask_apispec/wrapper.py | 5 ++++- tests/test_views.py | 24 +++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/flask_apispec/wrapper.py b/flask_apispec/wrapper.py index 067261f..b771eca 100644 --- a/flask_apispec/wrapper.py +++ b/flask_apispec/wrapper.py @@ -43,8 +43,11 @@ def call_view(self, *args, **kwargs): parsed = parser.parse(schema, locations=option['kwargs']['locations']) if getattr(schema, 'many', False): args += tuple(parsed) - else: + elif getattr(parsed, 'update', False): kwargs.update(parsed) + else: + args += (parsed, ) + return self.func(*args, **kwargs) def marshal_result(self, unpacked, status_code): diff --git a/tests/test_views.py b/tests/test_views.py index 23e8365..521e822 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -3,7 +3,7 @@ import json from flask import make_response -from marshmallow import fields, Schema +from marshmallow import fields, Schema, post_load from flask_apispec.utils import Ref from flask_apispec.views import MethodResource @@ -30,6 +30,28 @@ def view(**kwargs): res = client.get('/', {'name': 'freddie'}) assert res.json == {'name': 'freddie'} + def test_use_kwargs_schema_with_post_load(self, app, client): + class User: + def __init__(self, name): + self.name = name + + class ArgSchema(Schema): + name = fields.Str() + + @post_load + def make_object(self, data): + return User(**data) + + @app.route('/', methods=('POST', )) + @use_kwargs(ArgSchema()) + def view(user): + assert isinstance(user, User) + return {'name': user.name} + + data = {'name': 'freddie'} + res = client.post('/', data) + assert res.json == data + def test_use_kwargs_schema_many(self, app, client): class ArgSchema(Schema): name = fields.Str() From 6ec36d3f4f50c5281c53ca9e9bb36fd234d04659 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Sat, 22 Jun 2019 18:25:34 -0400 Subject: [PATCH 2/2] Use type check instead duck-typing --- flask_apispec/wrapper.py | 11 +++++++---- tests/test_views.py | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/flask_apispec/wrapper.py b/flask_apispec/wrapper.py index b771eca..f04e6d0 100644 --- a/flask_apispec/wrapper.py +++ b/flask_apispec/wrapper.py @@ -1,15 +1,18 @@ # -*- coding: utf-8 -*- +try: + from collections.abc import Mapping +except ImportError: # Python 2 + from collections import Mapping -from six.moves import http_client as http import flask - +import marshmallow as ma import werkzeug +from six.moves import http_client as http from webargs import flaskparser from flask_apispec import utils -import marshmallow as ma MARSHMALLOW_VERSION_INFO = tuple( [int(part) for part in ma.__version__.split('.') if part.isdigit()] @@ -43,7 +46,7 @@ def call_view(self, *args, **kwargs): parsed = parser.parse(schema, locations=option['kwargs']['locations']) if getattr(schema, 'many', False): args += tuple(parsed) - elif getattr(parsed, 'update', False): + elif isinstance(parsed, Mapping): kwargs.update(parsed) else: args += (parsed, ) diff --git a/tests/test_views.py b/tests/test_views.py index 521e822..dcc5502 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -35,6 +35,9 @@ class User: def __init__(self, name): self.name = name + def update(self, name): + self.name = name + class ArgSchema(Schema): name = fields.Str()