Skip to content

Commit aa7b48a

Browse files
committed
Optimization: minimize instantiations of Schema in use_args
If a dict is passed as the argmap, we only need to generate and instantiate a Schema once Also, add a test for aiohttpparser's use_args with schema factory
1 parent 0d4cb95 commit aa7b48a

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

tests/test_aiohttp/test_aiohttpparser.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,26 @@ def echo_use_args(request, args):
124124
assert res.json == {'name': 'Joe'}
125125

126126

127+
def test_use_args_with_callable(app, client):
128+
129+
class MySchema(Schema):
130+
foo = fields.Field(missing=42)
131+
132+
def make_schema(req):
133+
return MySchema(context={'request': req})
134+
135+
@asyncio.coroutine
136+
@use_args(make_schema)
137+
def echo_use_args(request, args):
138+
return jsonify(args)
139+
140+
app.router.add_route('GET', '/use_args', echo_use_args)
141+
142+
res = client.get('/use_args')
143+
assert res.status_code == 200
144+
assert res.json == {'foo': 42}
145+
146+
127147
def test_use_kwargs_on_method(app, client):
128148
class Handler:
129149

webargs/async.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
"""Asynchronous request parser. Compatible with Python>=3.4."""
33
import asyncio
4+
import collections
45
import inspect
56
import functools
67

@@ -62,6 +63,10 @@ def use_args(self, argmap, req=None, locations=None, as_kwargs=False, validate=N
6263
"""
6364
locations = locations or self.locations
6465
request_obj = req
66+
# Optimization: If argmap is passed as a dictionary, we only need
67+
# to generate a Schema once
68+
if isinstance(argmap, collections.Mapping):
69+
argmap = core.argmap2schema(argmap)()
6570

6671
def decorator(func):
6772
req_ = request_obj

webargs/core.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import unicode_literals
33

4+
import collections
45
import functools
56
import inspect
67
import logging
@@ -282,8 +283,9 @@ def _get_schema(self, argmap, req):
282283
def parse(self, argmap, req=None, locations=None, validate=None, force_all=False):
283284
"""Main request parsing method.
284285
285-
:param dict argmap: Either a `marshmallow.Schema` or a `dict`
286-
of argname -> `marshmallow.fields.Field` pairs.
286+
:param argmap: Either a `marshmallow.Schema`, `dict`
287+
of argname -> `marshmallow.fields.Field` pairs, or a callable that returns
288+
a `marshmallow.Schema` instance.
287289
:param req: The request object to parse.
288290
:param tuple locations: Where on the request to search for values.
289291
Can include one or more of ``('json', 'querystring', 'form',
@@ -359,6 +361,10 @@ def greet(args):
359361
"""
360362
locations = locations or self.locations
361363
request_obj = req
364+
# Optimization: If argmap is passed as a dictionary, we only need
365+
# to generate a Schema once
366+
if isinstance(argmap, collections.Mapping):
367+
argmap = argmap2schema(argmap)()
362368

363369
def decorator(func):
364370
req_ = request_obj

0 commit comments

Comments
 (0)