-
-
Notifications
You must be signed in to change notification settings - Fork 158
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
RFC: support passing the whole parsed arguments as a keyword argument #830
Comments
Yeah, current naming is not that self-explanatory. We could change it and release a major. I'm short of better ideas, but open to suggestions. If we keep current names, I like the second option better, keep the However, unless I didn't understand the proposal, I don't think it makes sense for |
I agree with the premise of this issue and would like to do something about it, but I'm not sure we have my ideal solution in hand yet.
So I'm looking at names and thinking what we can do... I don't like proposal (2) above, given the two choices. Proposal (1) above, a new method, might be the easiest and most feasible path, but I'd rather we give that capability to Here's what I'd like to have in the future, just to spitball a bit:
I think we could introduce most of this in backwards compatible ways by adding |
Looks good! Your proposal is more complete and reasonable. I had something similar when I think about this at downstream (apiflask/apiflask#427). But I plan to set the location value as the argument name. Do you think it's a good idea? It's more intuitive and easy to declare: @app.post('/pets/<pet_id>')
@use_args(PetBodyIn, location='json') # -> json
@use_args(PetQueryIn, location='query') # -> query
def create_pet(pet_id, json, query):
pass The only problem is that the |
If we want to introduce this in v8.x of
This is probably only a problem for I don't have super-strong feelings about the naming, so long as it's clear that it's the parsed data coming from
I'm going to cool it for a bit so that @lafrech has a chance to weigh in -- I'd like to know if he likes where this is going. I think this is a good path if we're comfortable with the idea of deprecating passing data as positional arguments, and removing that in v9. It may force a lot of users to change their usage, but it makes things way clearer when decorators are stacked. |
Thanks for your thoughts on this. No strong feeling about a breaking change. A clear interface and less API surface is what matters. As long as no use case is left behind, a find'n replace breaking change doesn't bother me. I wouldn't put webargs in the name. Verbose indeed, plus webargs may be hidden in apiflask/smorest so the user doesn't have to know. Could be |
Haha, we could make a vote for these names. There are eight emoji actions for an issue comment. We could use them to vote for eight options :P. BTW, I like |
8.3.0 has been released with I really like the result and I hope everyone else does as well! I have considered trying out, in my own usage, using a wrapper which looks for my schema objects to have a class FrobulatorSchema(Schema):
foo = fields.Str()
webargs_arg_name = "frobulator"
@my_webargs_wrapper(FrobulatorSchema, location="json")
def myview(*, frobulator: dict): ... I haven't tried this yet and there's no feature in For now, I'm marking this as resolved by the 8.3.0 release. Thanks for filing this issue! |
I just saw this now, I think when you use the I understand that it'd be tricky to special-case the whole thing when there's only one use_args decorator on a function, but just a plain |
I'm not sure I'd call We still have a bit of leeway on this for 9.0 since the only behavior we've "locked in" is the 8.x I don't really like the idea of special-casing the single-decorator usage. Not from the perspective of messy implementation -- IMO it's messy but doable -- but because I think it's likely to confuse people. What if we made the default behavior, when if arg_name is None and not self.USE_ARGS_POSITIONAL:
- arg_name = f"{location}_args"
+ arg_name = self.get_default_arg_name(location, schema) where of course we just make a method def get_default_arg_name(self, location: str, schema: Schema) -> str:
return f"{location}_args" Then we just document + test it and it's easy to subclass and override the method. It's not the most elegant interface in the world, but you could do something like def get_default_arg_name(self, location: str, schema: Schema) -> str:
if location in {"json", "form", "json_or_form"}:
return "payload"
return f"{location}_args" or even def get_default_arg_name(self, location: str, schema: Schema) -> str:
if isinstance(schema, MySpecialSchemaDeclaringArgName):
return schema.arg_name
return f"{location}_args" I think I would use that last example myself, since it lets me have class FrobulatorInput(Schema):
arg_name = "frobulator_input" @ThiefMaster, if this solution appeals to you, to keep the current default but open up some avenues to tune it, let me know and I'll see if I can work up a PR to discuss it further. |
sounds like a perfect solution for me :) |
Hi team,
Currently, we provide two options to pass the parsed arguments to the view function:
use_args
use_kwargs
It seems there is a mismatch here.
use_args
passes the parsed arguments as a single positional argument, while theuse_kwargs
passes all the arguments as separate keyword arguments.I'm thinking of adding the missing feature between this mismatch, which is to support passing the whole parsed arguments as a keyword argument.
What are the benefits? It can help to ensure the natural order for Flask views:
Since the URL variables (i.e.
pet_id
) will be passed as keyword arguments, we have to declare the arguments from use_args first.Although we can use
use_kwargs
to pass all arguments as keyword arguments, but consider we will use three stackeduse_kwargs
and each schema contains five fields...I made some experiments, there are two ways to achieve this:
use_named_args
):arg_name
argument touse_args
anduse_kwargs
.Do you think it's a useful feature? Which solution is preferred?
I'm happy to submit a PR. Thanks!
Related issue: apiflask/apiflask#427
The text was updated successfully, but these errors were encountered: