Combine errors from nested `use_args` calls so that mixed locations still provide full errors in webargs 6.x
See original GitHub issueWon’t we need to merge error messages for the stacked case?
@use_args({"related_id": fields.Str(required=True))}, location="query"}) @use_args({"name": fields.Str(required=True))}, location="json")
{"related_id": ['Missing...'], "name": ["Missing..."]}
_Originally posted by @sloria in https://github.com/marshmallow-code/webargs/issues/419#issuecomment-525765453_
Supporting this is desirable, since otherwise you only get partial information about validation failures. IMO, the worst part is this: the behavior depends on the order of your use_args
calls.
I’ve been thinking about this only a little bit since that issue and I think what’s best is that use_args
calls stash their arguments somewhere and then process them “all at once” before the user-supplied function.
One potential implementation path:
use_args
adds its arguments to some private attribute of the decorated function likefunc.__webargs_use_args_schemas
(initialized as an empty list)- the innermost
use_args
call walks all of the__webargs_use_args_schemas
data and evaluates all of it capturing and combining anyValidationError
s - outer
use_args
calls add data to the “schema list” but return the function they were given without trying to do any parsing- we could detect this by having the innermost
use_args
set a flag like__webargs_is_use_args_wrapped
which we check withhasattr
- we could detect this by having the innermost
I’d also like to explore whether or not it would be safe to replace the use_args
callable with a callable object of our own design. That might make the implementation simpler than proposed above, but I’m not sure if it will work with all frameworks.
Some questions:
- Is this actually a good idea? Just because we can do this and it would be nice for users doesn’t mean that it’s worth the complexity. I’m worried that I’m looking at what’s possible rather than what’s wise.
- Is there a better way to do this than storing decorator arguments in a list?
- Once you’ve done a bunch of parsing and have multiple
ValidationError
s in hand, what’s the correct way to combine them?
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
I worked up a version of this and concluded that it’s definitely not worth the trouble. Even if you modify
use_args
to put parameters into a list, which turns out not to be so bad, you have to start tinkering with the way thatParser.parse_args
works too (to skip calling the error handler function).I can get it all working, but it’s not worth making things that much messier and harder to maintain.
Ultimately, this convinced me. I think you’re right.
@lafrech, thanks for taking the time to read this and talk about it. I’m going to close as a wontfix and look at other things which are worth doing for 6.0.
Oh, you mean it may be too hard to let
use_args
do that but we could come up with another decorator that would do the two calls in one go so that we have the information about the schemas in the same decorator. Like theuse_args_by_location
.Frankly, I wouldn’t bother. As I said:
From a security perspective, the app is covered. It’s all about client-friendliness. It’s nice to be able to return all errors from a JSON input at once rather than one by one, as the cardinality could go high. But dealing with query args first then JSON is not a big issue to me. Assuming two, three nested calls at worse, that’s still a reasonable figure for a trial and error approach. Typically, only the body has a lot of fields.