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

Added support for giving multiple decorators to a route #157

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ nosetests.xml
.project
.pydevproject

# PyCharm
# Editors
.idea
.vscode

*.db
16 changes: 10 additions & 6 deletions flask_potion/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from collections import OrderedDict
import inspect
import operator
from functools import partial
from functools import partial, reduce
from flask import current_app, make_response, json, Response, request
from six import wraps
from werkzeug.exceptions import HTTPException
Expand Down Expand Up @@ -180,15 +180,19 @@ def _schema_view(self):

return OrderedDict(schema), 200, {'Content-Type': 'application/schema+json'}

def add_route(self, route, resource, endpoint=None, decorator=None):
def add_route(self, route, resource, endpoint=None, decorators=None):
endpoint = endpoint or '_'.join((resource.meta.name, route.relation))
methods = [route.method]
rule = route.rule_factory(resource)

view_func = route.view_factory(endpoint, resource)

if decorator:
view_func = decorator(view_func)
if not decorators:
pass
elif callable(decorators):
view_func = decorators(view_func)
else:
view_func = reduce(lambda f, dec: dec(f), decorators, view_func)

if self.app and not self.blueprint:
self._register_view(self.app, rule, view_func, endpoint, methods, route.relation)
Expand Down Expand Up @@ -222,8 +226,8 @@ def add_resource(self, resource):
resource.route_prefix = ''.join((self.prefix, '/', resource.meta.name))

for route in resource.routes.values():
route_decorator = resource.meta.route_decorators.get(route.relation, None)
self.add_route(route, resource, decorator=route_decorator)
route_decorators = resource.meta.route_decorators.get(route.relation, None)
self.add_route(route, resource, decorators=route_decorators)

for name, rset in inspect.getmembers(resource, lambda m: isinstance(m, RouteSet)):
if rset.attribute is None:
Expand Down
3 changes: 2 additions & 1 deletion flask_potion/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class Resource(six.with_metaclass(ResourceMeta, object)):
exclude_routes ``()`` A list of strings; any routes --- including inherited routes --- whose ``Route.relation``
match one of these string is omitted from the resource.
route_decorators ``{}`` A dictionary of decorators to apply to routes in the resource.
The keys must match the ``Route.relation`` attribute.
The keys must match the ``Route.relation`` attribute. The values can be
decorators or lists of decorators.
exclude_fields ``()`` A list of fields that should not be imported from the `model`.
required_fields ``()`` Fields that are automatically imported from the model are automatically
required if their columns are not `nullable` and do not have a `default`.
Expand Down
11 changes: 10 additions & 1 deletion tests/test_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,17 +260,23 @@ def simple_decorator(self):
def unauthorize_decorator(self):
return 'normal'

@Route.GET
def multiple_decorators(self):
return 'normal'

class Meta:
name = 'foo'
title = 'Foo bar'
route_decorators = {
'readSimpleDecorator': denormalize,
'readUnauthorizeDecorator': unauthorize
'readUnauthorizeDecorator': unauthorize,
'readMultipleDecorators': [denormalize] * 2
}

self.assertEqual('normal', FooResource().no_decorator())
self.assertEqual('normal', FooResource().simple_decorator())
self.assertEqual('normal', FooResource().unauthorize_decorator())
self.assertEqual('normal', FooResource().multiple_decorators())

api = Api(self.app)
api.add_resource(FooResource)
Expand All @@ -281,6 +287,9 @@ class Meta:
response = self.client.get("/foo/simple-decorator")
self.assertEqual('not normal', response.json)

response = self.client.get("/foo/multiple-decorators")
self.assertEqual('not not normal', response.json)

response = self.client.get("/foo/unauthorize-decorator")
self.assert401(response)

Expand Down