Skip to content

Commit 2fd3450

Browse files
committed
Fixup the 6.0 upgrading doc
Mostly per review from @lafrech, but this also fixes the pyramid parser change doc. `request` is always passed first, but other argument ordering is inverted in `@use_args`. Additionally, this fixes all of the `use_args` calls to have less confusing parameter names. Because it passes the args as a dict, use the name `args` and show it can be accessed with `args.get("q")` in each case. Naming the arg dict `q` after the only field used could suggest to users that `use_args` passes fields individually in some way.
1 parent f1e876e commit 2fd3450

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

docs/upgrading.rst

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@ This section documents migration paths to new releases.
66
Upgrading to 6.0
77
++++++++++++++++
88

9-
In webargs 6, the way that data is loaded from various locations and passed to
10-
your schemas changed significantly. This may require you to change several
11-
different parts of your webargs usage.
12-
13-
Multiple locations are no longer supported in a single call
9+
Multiple Locations Are No Longer Supported In A Single Call
1410
-----------------------------------------------------------
1511

16-
And only JSON data is parsed by default.
12+
The default location is JSON/body.
1713

1814
Under webargs 5.x, you may have written code which did not specify a location.
1915

@@ -29,23 +25,24 @@ parameter, you must be explicit and rewrite like so:
2925
3026
# webargs 5.x
3127
@parser.use_args({"q": ma.fields.String()})
32-
def foo(q):
33-
return some_function(user_query=q)
28+
def foo(args):
29+
return some_function(user_query=args.get("q"))
3430
3531
3632
# webargs 6.x
3733
@parser.use_args({"q": ma.fields.String()}, location="query")
38-
def foo(q):
39-
return some_function(user_query=q)
34+
def foo(args):
35+
return some_function(user_query=args.get("q"))
4036
4137
This also means that another usage from 5.x is not supported. If you had code
4238
with multiple locations in a single `use_args`, `use_kwargs`, or `parse` call,
43-
you must write it in multiple separate `use_args` invocations, like so:
39+
you must write it in multiple separate `use_args` or `use_kwargs` invocations,
40+
like so:
4441

4542
.. code-block:: python
4643
4744
# webargs 5.x
48-
@parser.use_args(
45+
@parser.use_kwargs(
4946
{
5047
"q1": ma.fields.Int(location="query"),
5148
"q2": ma.fields.Int(location="query"),
@@ -58,13 +55,13 @@ you must write it in multiple separate `use_args` invocations, like so:
5855
5956
6057
# webargs 6.x
61-
@parser.use_args({"q1": ma.fields.Int(), "q2": ma.fields.Int()}, location="query")
62-
@parser.use_args({"h1": ma.fields.Int()}, location="headers")
58+
@parser.use_kwargs({"q1": ma.fields.Int(), "q2": ma.fields.Int()}, location="query")
59+
@parser.use_kwargs({"h1": ma.fields.Int()}, location="headers")
6360
def foo(q1, q2, h1):
6461
...
6562
6663
67-
Fields no longer support location=...
64+
Fields No Longer Support location=...
6865
-------------------------------------
6966

7067
Because a single `parser.use_args`, `parser.use_kwargs`, or `parser.parse` call
@@ -75,16 +72,16 @@ to specify its location. Rewrite code like so:
7572
7673
# webargs 5.x
7774
@parser.use_args({"q": ma.fields.String(location="query")})
78-
def foo(q):
79-
return some_function(user_query=q)
75+
def foo(args):
76+
return some_function(user_query=args.get("q"))
8077
8178
8279
# webargs 6.x
8380
@parser.use_args({"q": ma.fields.String()}, location="query")
84-
def foo(q):
85-
return some_function(user_query=q)
81+
def foo(args):
82+
return some_function(user_query=args.get("q"))
8683
87-
location_handler has been replaced with location_loader
84+
location_handler Has Been Replaced With location_loader
8885
-------------------------------------------------------
8986

9087
This is not just a name change. The expected signature of a `location_loader`
@@ -108,17 +105,17 @@ Rewrite code like this:
108105
def load_data(request, schema):
109106
return request.data
110107
111-
Data is not filtered before being passed to your schema, and it may be proxified
108+
Data Is Not Filtered Before Being Passed To Your Schema, And It May Be Proxified
112109
--------------------------------------------------------------------------------
113110

114-
In webargs 5.x, the schema you gave was used to pull data out of the request
115-
object. That data was compiled into a dictionary which was then passed to your
116-
schema.
111+
In webargs 5.x, the deserialization schema was used to pull data out of the
112+
request object. That data was compiled into a dictionary which was then passed
113+
to the schema.
117114

118115
One of the major changes in webargs 6.x allows the use of `unknown` parameter
119116
on schemas. This lets a schema decide what to do with fields not specified in
120117
the schema. In order to achieve this, webargs now passes the full data from
121-
the location you selected to your schema.
118+
the specified location to the schema.
122119

123120
However, many types of request data are so-called "multidicts" -- dictionary-like
124121
types which can return one or multiple values as you prefer. To handle
@@ -230,7 +227,7 @@ the data in-place. You may need to apply rewrites like so:
230227
...
231228
232229
233-
DelimitedList now only takes a string input
230+
DelimitedList Now Only Takes A String Input
234231
-------------------------------------------
235232

236233
Combining `List` and string parsing functionality in a single type had some
@@ -274,7 +271,7 @@ you need to allow both usages in your API, you can do a rewrite like so:
274271
...
275272
276273
277-
ValidationError messages are namespaced under the location
274+
ValidationError Messages Are Namespaced Under The Location
278275
----------------------------------------------------------
279276

280277
If you were parsing ValidationError messages, you will notice a change in the
@@ -312,7 +309,7 @@ to traverse messages by one additional level. For example:
312309
log.debug("bad value for '{}' [{}]: {}".format(field, location, messages))
313310
314311
315-
Some functions take keyword-only arguments now
312+
Some Functions Take Keyword-Only Arguments Now
316313
----------------------------------------------
317314

318315
The signature of several methods has changed to have keyword-only arguments.
@@ -422,26 +419,58 @@ and finally, the `dict2schema` function:
422419
...
423420
424421
425-
PyramidParser now appends arguments (used to prepend)
422+
PyramidParser Now Appends Arguments (Used To Prepend)
426423
-----------------------------------------------------
427424

428425
`PyramidParser.use_args` was not conformant with the other parsers in webargs.
429426
While all other parsers added new arguments to the end of the argument list of
430427
a decorated view function, the Pyramid implementation added them to the front
431-
of the argument list. This has been corrected, but as a result pyramid views
432-
with `use_args` will need to be rewritten like so:
428+
of the argument list.
429+
430+
This has been corrected, but as a result pyramid views with `use_args` may need
431+
to be rewritten. The `request` object is always passed first in both versions,
432+
so the issue is only apparent with view functions taking other positional
433+
arguments.
434+
435+
For example, imagine code with a decorator for passing user information,
436+
`pass_userinfo`, like so:
437+
438+
.. code-block:: python
439+
440+
# a decorator which gets information about the authenticated user
441+
def pass_userinfo(f):
442+
def decorator(request, *args, **kwargs):
443+
return f(request, get_userinfo(), *args, **kwargs)
444+
445+
return decorator
446+
447+
You will see a behavioral change if `pass_userinfo` is called on a function
448+
decorated with `use_args`. The difference between the two versions will be like
449+
so:
433450

434451
.. code-block:: python
435452
436453
from webargs.pyramidparser import use_args
437454
438455
# webargs 5.x
456+
# pass_userinfo is called first, webargs sees positional arguments of
457+
# (userinfo,)
458+
# and changes it to
459+
# (request, args, userinfo)
460+
@pass_userinfo
439461
@use_args({"q": ma.fields.String()}, locations=("query",))
440-
def viewfunc(q, request):
462+
def viewfunc(request, args, userinfo):
463+
q = args.get("q")
441464
...
442465
443466
444467
# webargs 6.x
468+
# pass_userinfo is called first, webargs sees positional arguments of
469+
# (userinfo,)
470+
# and changes it to
471+
# (request, userinfo, args)
472+
@pass_userinfo
445473
@use_args({"q": ma.fields.String()}, location="query")
446-
def viewfunc(request, q):
474+
def viewfunc(request, userinfo, args):
475+
q = args.get("q")
447476
...

0 commit comments

Comments
 (0)