Skip to content

Commit 3020476

Browse files
authored
Merge pull request #478 from marshmallow-code/pylint
Minor refactors and pylint fixes
2 parents 936a6bb + 97f2d8e commit 3020476

15 files changed

+79
-89
lines changed

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ Features:
1010
provide compatibility with ``falcon.testing`` (:pr:`477`).
1111
Thanks :user:`suola` for the PR.
1212

13+
* *Backwards-incompatible*: Factorize the ``use_args`` / ``use_kwargs`` branch
14+
in all parsers. When ``as_kwargs`` is ``False``, arguments are now
15+
consistently appended to the arguments list by the ``use_args`` decorator.
16+
Before this change, the ``PyramidParser`` would prepend the argument list on
17+
each call to ``use_args``. Pyramid view functions must reverse the order of
18+
their arguments. (:pr:`478`)
1319

1420
6.0.0b8 (2020-02-16)
1521
********************

src/webargs/aiohttpparser.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,12 @@ async def load_json(self, req: Request, schema: Schema) -> typing.Dict:
101101
return core.missing
102102
try:
103103
return await req.json(loads=json.loads)
104-
except json.JSONDecodeError as e:
105-
if e.doc == "":
104+
except json.JSONDecodeError as exc:
105+
if exc.doc == "":
106106
return core.missing
107-
else:
108-
return self._handle_invalid_json_error(e, req)
109-
except UnicodeDecodeError as e:
110-
return self._handle_invalid_json_error(e, req)
107+
return self._handle_invalid_json_error(exc, req)
108+
except UnicodeDecodeError as exc:
109+
return self._handle_invalid_json_error(exc, req)
111110

112111
def load_headers(self, req: Request, schema: Schema) -> MultiDictProxy:
113112
"""Return headers from the request as a MultiDictProxy."""
@@ -138,7 +137,7 @@ def get_request_from_view_args(
138137
if isinstance(arg, web.Request):
139138
req = arg
140139
break
141-
elif isinstance(arg, web.View):
140+
if isinstance(arg, web.View):
142141
req = arg.request
143142
break
144143
if not isinstance(req, web.Request):

src/webargs/asyncparser.py

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,10 @@ async def wrapper(*args, **kwargs):
147147
error_status_code=error_status_code,
148148
error_headers=error_headers,
149149
)
150-
if as_kwargs:
151-
kwargs.update(parsed_args or {})
152-
return await func(*args, **kwargs)
153-
else:
154-
# Add parsed_args after other positional arguments
155-
new_args = args + (parsed_args,)
156-
return await func(*new_args, **kwargs)
150+
args, kwargs = self._update_args_kwargs(
151+
args, kwargs, parsed_args, as_kwargs
152+
)
153+
return await func(*args, **kwargs)
157154

158155
else:
159156

@@ -172,22 +169,11 @@ def wrapper(*args, **kwargs):
172169
error_status_code=error_status_code,
173170
error_headers=error_headers,
174171
)
175-
if as_kwargs:
176-
kwargs.update(parsed_args)
177-
return func(*args, **kwargs) # noqa: B901
178-
else:
179-
# Add parsed_args after other positional arguments
180-
new_args = args + (parsed_args,)
181-
return func(*new_args, **kwargs)
172+
args, kwargs = self._update_args_kwargs(
173+
args, kwargs, parsed_args, as_kwargs
174+
)
175+
return func(*args, **kwargs)
182176

183177
return wrapper
184178

185179
return decorator
186-
187-
def use_kwargs(self, *args, **kwargs) -> typing.Callable:
188-
"""Decorator that injects parsed arguments into a view function or method.
189-
190-
Receives the same arguments as `webargs.core.Parser.use_kwargs`.
191-
192-
"""
193-
return super().use_kwargs(*args, **kwargs)

src/webargs/bottleparser.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ def _raw_load_json(self, req):
4545
# see: https://github.com/bottlepy/bottle/issues/1160
4646
if data is None:
4747
return core.missing
48-
else:
49-
return data
48+
return data
5049

5150
def load_querystring(self, req, schema):
5251
"""Return query params from the request as a MultiDictProxy."""

src/webargs/core.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import functools
22
import inspect
3+
import typing
34
import logging
45
import warnings
56
from collections.abc import Mapping
@@ -35,8 +36,7 @@ def _callable_or_raise(obj):
3536
"""
3637
if obj and not callable(obj):
3738
raise ValueError("{!r} is not callable.".format(obj))
38-
else:
39-
return obj
39+
return obj
4040

4141

4242
def is_multiple(field):
@@ -66,17 +66,17 @@ def is_json(mimetype):
6666
return False
6767

6868

69-
def parse_json(s, *, encoding="utf-8"):
70-
if isinstance(s, bytes):
69+
def parse_json(string, *, encoding="utf-8"):
70+
if isinstance(string, bytes):
7171
try:
72-
s = s.decode(encoding)
73-
except UnicodeDecodeError as e:
72+
string = string.decode(encoding)
73+
except UnicodeDecodeError as exc:
7474
raise json.JSONDecodeError(
75-
"Bytes decoding error : {}".format(e.reason),
76-
doc=str(e.object),
77-
pos=e.start,
75+
"Bytes decoding error : {}".format(exc.reason),
76+
doc=str(exc.object),
77+
pos=exc.start,
7878
)
79-
return json.loads(s)
79+
return json.loads(string)
8080

8181

8282
def _ensure_list_of_callables(obj):
@@ -291,6 +291,16 @@ def get_request_from_view_args(self, view, args, kwargs):
291291
"""
292292
return None
293293

294+
@staticmethod
295+
def _update_args_kwargs(args, kwargs, parsed_args, as_kwargs):
296+
"""Update args or kwargs with parsed_args depending on as_kwargs"""
297+
if as_kwargs:
298+
kwargs.update(parsed_args)
299+
else:
300+
# Add parsed_args after other positional arguments
301+
args += (parsed_args,)
302+
return args, kwargs
303+
294304
def use_args(
295305
self,
296306
argmap,
@@ -350,20 +360,17 @@ def wrapper(*args, **kwargs):
350360
error_status_code=error_status_code,
351361
error_headers=error_headers,
352362
)
353-
if as_kwargs:
354-
kwargs.update(parsed_args)
355-
return func(*args, **kwargs)
356-
else:
357-
# Add parsed_args after other positional arguments
358-
new_args = args + (parsed_args,)
359-
return func(*new_args, **kwargs)
363+
args, kwargs = self._update_args_kwargs(
364+
args, kwargs, parsed_args, as_kwargs
365+
)
366+
return func(*args, **kwargs)
360367

361368
wrapper.__wrapped__ = func
362369
return wrapper
363370

364371
return decorator
365372

366-
def use_kwargs(self, *args, **kwargs):
373+
def use_kwargs(self, *args, **kwargs) -> typing.Callable:
367374
"""Decorator that injects parsed arguments into a view function or method
368375
as keyword arguments.
369376
@@ -456,12 +463,12 @@ def load_json(self, req, schema):
456463
# code sharing amongst the built-in webargs parsers
457464
try:
458465
return self._raw_load_json(req)
459-
except json.JSONDecodeError as e:
460-
if e.doc == "":
466+
except json.JSONDecodeError as exc:
467+
if exc.doc == "":
461468
return missing
462-
return self._handle_invalid_json_error(e, req)
463-
except UnicodeDecodeError as e:
464-
return self._handle_invalid_json_error(e, req)
469+
return self._handle_invalid_json_error(exc, req)
470+
except UnicodeDecodeError as exc:
471+
return self._handle_invalid_json_error(exc, req)
465472

466473
def load_json_or_form(self, req, schema):
467474
"""Load data from a request, accepting either JSON or form-encoded

src/webargs/falconparser.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ def _raw_load_json(self, req):
106106
body = req.stream.read(req.content_length)
107107
if body:
108108
return core.parse_json(body)
109-
else:
110-
return core.missing
109+
return core.missing
111110

112111
def load_headers(self, req, schema):
113112
"""Return headers from the request."""

src/webargs/multidictproxy.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
from collections.abc import Mapping
2+
13
from webargs.compat import MARSHMALLOW_VERSION_INFO
24
from webargs.core import missing, is_multiple
35

4-
from collections.abc import Mapping
5-
66

77
class MultiDictProxy(Mapping):
88
"""
@@ -18,7 +18,8 @@ def __init__(self, multidict, schema):
1818
self.data = multidict
1919
self.multiple_keys = self._collect_multiple_keys(schema)
2020

21-
def _collect_multiple_keys(self, schema):
21+
@staticmethod
22+
def _collect_multiple_keys(schema):
2223
result = set()
2324
for name, field in schema.fields.items():
2425
if not is_multiple(field):
@@ -35,9 +36,9 @@ def __getitem__(self, key):
3536
return val
3637
if hasattr(self.data, "getlist"):
3738
return self.data.getlist(key)
38-
elif hasattr(self.data, "getall"):
39+
if hasattr(self.data, "getall"):
3940
return self.data.getall(key)
40-
elif isinstance(val, (list, tuple)):
41+
if isinstance(val, (list, tuple)):
4142
return val
4243
if val is None:
4344
return None

src/webargs/pyramidparser.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,10 @@ def wrapper(obj, *args, **kwargs):
159159
error_status_code=error_status_code,
160160
error_headers=error_headers,
161161
)
162-
if as_kwargs:
163-
kwargs.update(parsed_args)
164-
return func(obj, *args, **kwargs)
165-
else:
166-
return func(obj, parsed_args, *args, **kwargs)
162+
args, kwargs = self._update_args_kwargs(
163+
args, kwargs, parsed_args, as_kwargs
164+
)
165+
return func(obj, *args, **kwargs)
167166

168167
wrapper.__wrapped__ = func
169168
return wrapper

src/webargs/tornadoparser.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,16 @@ def __getitem__(self, key):
4646
value = self.data.get(key, core.missing)
4747
if value is core.missing:
4848
return core.missing
49-
elif key in self.multiple_keys:
49+
if key in self.multiple_keys:
5050
return [
5151
_unicode(v) if isinstance(v, (str, bytes)) else v for v in value
5252
]
53-
elif value and isinstance(value, (list, tuple)):
53+
if value and isinstance(value, (list, tuple)):
5454
value = value[0]
5555

5656
if isinstance(value, (str, bytes)):
5757
return _unicode(value)
58-
else:
59-
return value
58+
return value
6059
# based on tornado.web.RequestHandler.decode_argument
6160
except UnicodeDecodeError:
6261
raise HTTPError(400, "Invalid unicode in {}: {!r}".format(key, value[:40]))
@@ -73,10 +72,9 @@ def __getitem__(self, key):
7372
cookie = self.data.get(key, core.missing)
7473
if cookie is core.missing:
7574
return core.missing
76-
elif key in self.multiple_keys:
75+
if key in self.multiple_keys:
7776
return [cookie.value]
78-
else:
79-
return cookie.value
77+
return cookie.value
8078

8179

8280
class TornadoParser(core.Parser):

tests/apps/aiohttp_app.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import asyncio
22

33
import aiohttp
4-
import marshmallow as ma
5-
from aiohttp import web
64
from aiohttp.web import json_response
5+
import marshmallow as ma
6+
77
from webargs import fields
88
from webargs.aiohttpparser import parser, use_args, use_kwargs
99
from webargs.core import MARSHMALLOW_VERSION_INFO, json
@@ -48,7 +48,7 @@ async def echo_json(request):
4848
try:
4949
parsed = await parser.parse(hello_args, request, location="json")
5050
except json.JSONDecodeError:
51-
raise web.HTTPBadRequest(
51+
raise aiohttp.web.HTTPBadRequest(
5252
body=json.dumps(["Invalid JSON."]).encode("utf-8"),
5353
content_type="application/json",
5454
)
@@ -59,7 +59,7 @@ async def echo_json_or_form(request):
5959
try:
6060
parsed = await parser.parse(hello_args, request, location="json_or_form")
6161
except json.JSONDecodeError:
62-
raise web.HTTPBadRequest(
62+
raise aiohttp.web.HTTPBadRequest(
6363
body=json.dumps(["Invalid JSON."]).encode("utf-8"),
6464
content_type="application/json",
6565
)
@@ -184,7 +184,7 @@ async def get(self, request, args):
184184
return json_response(args)
185185

186186

187-
class EchoHandlerView(web.View):
187+
class EchoHandlerView(aiohttp.web.View):
188188
@asyncio.coroutine
189189
@use_args(hello_args, location="query")
190190
def get(self, args):

0 commit comments

Comments
 (0)